2010-07-09 2 views
18

Le example fournit un extrait pour une vue au niveau de l'application, mais que se passe-t-il si j'ai plusieurs entrées différentes (et certaines non-applications) dans mon fichier "urls.py", y compris les modèles? Comment puis-je appliquer ce décorateur login_required à chacun d'entre eux?Django: Comment puis-je appliquer le décorateur login_required à l'ensemble de mon site (à l'exclusion des médias statiques)?

(r'^foo/(?P<slug>[-\w]+)/$', 'bugs.views.bug_detail'), 
(r'^$', 'django.views.generic.simple.direct_to_template', {'template':'homepage.html'}), 

Répondre

24

abandonné cette dans un fichier middleware.py dans ma racine du projet (prise de http://onecreativeblog.com/post/59051248/django-login-required-middleware)

from django.http import HttpResponseRedirect 
from django.conf import settings 
from re import compile 

EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))] 
if hasattr(settings, 'LOGIN_EXEMPT_URLS'): 
    EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS] 

class LoginRequiredMiddleware: 
    """ 
    Middleware that requires a user to be authenticated to view any page other 
    than LOGIN_URL. Exemptions to this requirement can optionally be specified 
    in settings via a list of regular expressions in LOGIN_EXEMPT_URLS (which 
    you can copy from your urls.py). 

    Requires authentication middleware and template context processors to be 
    loaded. You'll get an error if they aren't. 
    """ 
    def process_request(self, request): 
     assert hasattr(request, 'user'), "The Login Required middleware\ 
requires authentication middleware to be installed. Edit your\ 
MIDDLEWARE_CLASSES setting to insert\ 
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\ 
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\ 
'django.core.context_processors.auth'." 
     if not request.user.is_authenticated(): 
      path = request.path_info.lstrip('/') 
      if not any(m.match(path) for m in EXEMPT_URLS): 
       return HttpResponseRedirect(settings.LOGIN_URL) 

ensuite ajouté projectname.middleware.LoginRequiredMiddleware à mes MIDDLEWARE_CLASSES en settings.py.

+5

Je pense que cette solution est vraiment géniale. J'ai [accordé] (https://gist.github.com/TomasTomecek/5056424) un peu pour supporter 'redirect' et obtenir l'URL de connexion via' reverse'. – SummerBreeze

+0

Je pense que l'auteur devrait également citer http://onecreativeblog.com/post/59051248/django-login-required-middleware –

+0

cela ne fonctionne pas si LOGIN_URL = '/' car après avoir enlevé la barre oblique en haut de cette extrait de code, la chaîne vide résultante correspond à n'importe quelle URL! – user3182532

2

Utilisez le middleware.

http://www.djangobook.com/en/2.0/chapter17/ et http://docs.djangoproject.com/en/1.2/topics/http/middleware/#topics-http-middleware

Je suppose que cela n'a pas changé beaucoup dans 1,2

Middleware vous permet de créer une classe avec des méthodes qui traitera chaque demande à différents moments/conditions , comme vous le définissez. Par exemple, process_request (request) se déclencherait avant votre vue, et vous pouvez forcer l'authentification et l'autorisation à ce stade.

+1

Vous devriez élaborer. –

+0

Je ne suis pas familier avec l'utilisation de middleware personnalisé. Pouvez-vous indiquer un extrait compatible avec django 1.2 qui gère cela? –

+0

Je suis tombé sur cet extrait: http://djangosnippets.org/snippets/1179/ Bien qu'il a été posté en 2008. Quelqu'un peut-il parcourir et voir si ce serait utilisable? –

11

Pour ceux qui sont venus plus tard, vous pourriez trouver que django-stronghold correspond bien à votre cas. Vous mettez en liste blanche toutes les URL que vous voulez public, le reste est nécessaire.

https://github.com/mgrouchy/django-stronghold

+1

Cette solution semble beaucoup plus élégante que l'installation et la maintenance de votre propre middleware. Fonctionne très bien. – shacker

+0

J'ai créé un '' middleware.py' contenant de MiddlewareMixin' import de django.utils.deprecation, 'de LoginRequiredMiddleware' d'importation stronghold.middleware, classe' LoginRequiredStrongholdMiddleware (MiddlewareMixin, LoginRequiredMiddleware): pass'. Ensuite, j'ai ajouté cette classe de middleware personnalisée dans le fichier de paramètres plutôt que la classe de bastion par défaut. Cela a fonctionné dans Django 1.10 – MiniGunnR

7

est ici un middleware légèrement plus courte.

from django.contrib.auth.decorators import login_required 

class LoginRequiredMiddleware(object): 
    def process_view(self, request, view_func, view_args, view_kwargs): 
     if not getattr(view_func, 'login_required', True): 
      return None 
     return login_required(view_func)(request, *view_args, **view_kwargs) 

Vous devez définir "login_required" False sur chaque vue que vous n'avez pas besoin d'être connecté pour voir:

fonction vues:

def someview(request, *args, **kwargs): 
    # body of view 
someview.login_required = False 

CLASS- vues sur la base:

class SomeView(View): 
    login_required = False 
    # body of view 

#or 

class SomeView(View): 
    # body of view 
someview = SomeView.as_view() 
someview.login_required = False 

Cela signifie que vous aurez à faire quelque chose au sujet des vues de login, mais je finis toujours par écrire mon propre auth-b Ackend quand même.

0

En plus de Meder Omuraliev réponse si vous voulez url exempté comme celui-ci (avec regexp):

url(r'^my/url/(?P<pk>[0-9]+)/$', views.my_view, name='my_url') 

ajouter à EXEMPT_URLS liste comme ceci:

LOGIN_EXEMPT_URLS = [r'^my/url/([0-9]+)/$'] 

r ». . ' au début de la chaîne nécessaire.

-1

Voici un exemple de middleware nouveau style dans Django 1.10+:

from django.contrib.auth.decorators import login_required 
from django.urls import reverse 

def login_required_middleware(get_response): 
    """ 
     Require user to be logged in for all views. 
    """ 
    exceptions = {'/admin/login/'} 
    def middleware(request): 
     if request.path in exceptions: 
      return get_response(request) 
     return login_required(get_response, login_url=reverse('admin:login'))(request) 
    return middleware 

Cet exemple dispense le formulaire de connexion d'administrateur pour éviter la boucle de redirection et utilise ce formulaire comme URL de connexion.

0

Django Connexion Middleware requis

Mettez ce code dans middleware.py:

from django.http import HttpResponseRedirect 
from django.conf import settings 
from django.utils.deprecation import MiddlewareMixin 
from re import compile 

EXEMPT_URLS = [compile(settings.LOGIN_URL.lstrip('/'))] 
if hasattr(settings, 'LOGIN_EXEMPT_URLS'): 
    EXEMPT_URLS += [compile(expr) for expr in settings.LOGIN_EXEMPT_URLS] 

class LoginRequiredMiddleware(MiddlewareMixin): 
    def process_request(self, request): 
     assert hasattr(request, 'user') 
     if not request.user.is_authenticated: 
      path = request.path_info.lstrip('/') 
      if not any(m.match(path) for m in EXEMPT_URLS): 
       return HttpResponseRedirect(settings.LOGIN_URL) 

Et, en settings.py:

LOGIN_URL = '/app_name/login' 

LOGIN_EXEMPT_URLS=(
    r'/app_name/login/', 
) 

MIDDLEWARE_CLASSES = (
    # ... 
    'python.path.to.LoginRequiredMiddleware', 
) 

Comme ceci: « app_name. middleware.LoginRequiredMiddleware '

Questions connexes