Django: Как я могу применить декоратор login_required ко всему моему сайту (кроме статических носителей)? - PullRequest
22 голосов
/ 09 июля 2010

Пример предоставляет фрагмент для представления уровня приложения, но что если в моем файле "urls.py", включая шаблоны, есть много разных (и не относящихся к приложениям) записей, включая шаблоны? Как я могу применить этот login_required декоратор к каждому из них?

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

Ответы [ 9 ]

27 голосов
/ 13 июля 2010

Перенес это в файл middleware.py в корне моего проекта (взято из 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)

Затем добавлено projectname.middleware.LoginRequiredMiddleware к моему MIDDLEWARE_CLASSES в settings.py.

13 голосов
/ 17 февраля 2013

Для тех, кто пришел к этому позже, вы можете обнаружить, что django-stronghold хорошо вписывается в ваш вариант использования.Вы вносите в белый список любые URL, которые хотите опубликовать, а остальные - для входа в систему.

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

8 голосов
/ 13 мая 2013

Вот немного более короткое промежуточное ПО.

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)

Вам нужно будет установить "login_required" в False для каждого представления, в которое вам не нужно входить, чтобы увидеть:

Функция-вид:

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

Просмотры на основе класса:

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

#or

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

Это означает, что вам придется что-то делать с представлениями входа в систему, но я всегда заканчиваю тем, что пишу свой собственный auth-backend.

3 голосов
/ 06 апреля 2018

Вот классическая LoginRequiredMiddleware для Джанго 1.10 +:

from django.utils.deprecation import MiddlewareMixin

class LoginRequiredMiddleware(MiddlewareMixin):
    """
    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).
    """
    def process_request(self, request):
        assert hasattr(request, 'user'), """
        The Login Required middleware needs to be after AuthenticationMiddleware.
        Also make sure to include the template context_processor:
        'django.contrib.auth.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)

Примечательные отличия:

  • path.to.LoginRequiredMiddleware должен быть включен в MIDDLEWARE, а не MIDDLEWARE_CLASSES в settings.py.
  • is_authenticated это бул, а не метод.
  • см. документы для получения дополнительной информации (хотя некоторые части не очень ясны).
2 голосов
/ 09 июля 2010

Использовать промежуточное ПО.

http://www.djangobook.com/en/2.0/chapter17/ а также http://docs.djangoproject.com/en/1.2/topics/http/middleware/#topics-http-middleware

Я предполагаю, что это не сильно изменилось в 1.2

Промежуточное программное обеспечение позволяет вам создать класс с методами, которые будут обрабатывать каждый запрос в разное время / условия, как вы определяете.

например, process_request (запрос) будет запущен перед вашим просмотром, и вы можете принудительно установить аутентификацию и авторизацию на этом этапе.

1 голос
/ 13 июня 2019

Некоторые из предыдущих ответов либо устарели (более старая версия Django), либо вводят плохие методы программирования (жесткое кодирование URL, не использующее маршруты).Вот мое мнение о том, что оно более СУХОЕ и устойчивое / обслуживаемое (адаптировано из Ответ Мехмета выше ).

Чтобы подчеркнуть здесь улучшения, это полагается на предоставление URL-адресов маршрутов (которые гораздо более надежны)чем использование жестко закодированных URL / URI, которые изменяются и имеют конечные / начальные слэши).

from django.utils.deprecation import MiddlewareMixin
from django.urls import resolve, reverse
from django.http import HttpResponseRedirect
from my_project import settings

class LoginRequiredMiddleware(MiddlewareMixin):
    """
    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 by setting a tuple of routes to ignore
    """
    def process_request(self, request):
        assert hasattr(request, 'user'), """
        The Login Required middleware needs to be after AuthenticationMiddleware.
        Also make sure to include the template context_processor:
        'django.contrib.auth.context_processors.auth'."""

        if not request.user.is_authenticated:
            current_route_name = resolve(request.path_info).url_name

            if not current_route_name in settings.AUTH_EXEMPT_ROUTES:
                return HttpResponseRedirect(reverse(settings.AUTH_LOGIN_ROUTE))

А в файле settings.py вы можете определить следующее:

AUTH_EXEMPT_ROUTES = ('register', 'login', 'forgot-password')
AUTH_LOGIN_ROUTE = 'register'
0 голосов
/ 14 февраля 2018

Промежуточное ПО для входа в Django

Поместите этот код в 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)

И в settings.py:

LOGIN_URL = '/app_name/login'

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

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

Например: 'app_name.middleware.LoginRequiredMiddleware'

0 голосов
/ 26 мая 2017

Вот пример промежуточного программного обеспечения в 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

В этом примере исключается форма входа в систему администратора, чтобы избежать цикла перенаправления, и используется эта форма в качестве URL-адреса входа.

0 голосов
/ 14 сентября 2016

В дополнение к meder omuraliev ответьте, если хотите, чтобы URL-адрес освобождался, как этот (с регулярным выражением):

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

добавьте его в список EXEMPT_URLS следующим образом:

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

r '..' в начале необходимой строки.

...