Я использую django-decorator-include, чтобы использовать декоратор login_required
для защиты всего приложения. , а не по одному просмотру за раз. Основной urls.py моего приложения выглядит так:
path('my_secret_app/', decorator_include(login_required, ('my_secret_app.urls', 'my_secret_app'))),
Это прекрасно работает, за исключением случаев, когда одно из моих приложений имеет одно представление, которое должно быть общедоступным.
Чтобы обойти это, я написал свои собственные login_required
и login_not_required
. Мой login_required
основан на django.contrib.auth.decorators.login_required
django, но немного изменен, чтобы действительно учитывать, когда представление помечено как не требующее входа в систему.
Мой проект называется mysite
.
Мое приложение называется my_secret_app
.
Мое публичное представление в my_secret_app
называется MyPublicView
.
Все мое решение выглядит так:
мой сайт/lib.py
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import user_passes_test
# A copy of django.contrib.auth.decorators.login_required that looks for login_not_required attr
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
actual_decorator = user_passes_test(
lambda u: u.is_authenticated,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
login_req = getattr(function, "login_required", True)
if login_req:
return actual_decorator(function)
else:
return function
else:
return actual_decorator
# Decorator to mark a view as not requiring login to access
def login_not_required(f):
f.login_required = False
return f
мой сайт/urls.py
from .lib import login_required
path('my_secret_app/', decorator_include(login_required, ('my_secret_app.urls', 'my_secret_app'))),
my_secret_app/views.py:
from django.utils.decorators import method_decorator
from mysite.lib import login_not_required
class MyPublicView(View):
@method_decorator(login_not_required)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request):
...
def post(self, request, *args, **kwargs):
...
Вы должны иметь возможность делать то же самое, независимо от того, являетесь ли вы подклассом View
, ListView
, CreateView
, UpdateView
, TemplateView
или любым другим. Это также должно работать, если вы используете функцию в качестве своего представления, хотя я не пробовал:
@login_not_required
def MyPublicView(request):
...
person
John
schedule
20.01.2020