В декораторе нет ничего волшебного, это функция, которая принимает в качестве входных данных функцию (или класс) для декорирования и вносит в нее некоторые изменения. Если мы посмотрим на декоратор login_required
[GitHub] , мы увидим:
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator
Таким образом, мы на самом деле можем просто сделать специальный случай декоратора user_passes_test
:
from django.contrib.auth.decorators import user_passes_test
def shopkeeper_required(function=None):
def is_shopkeeper(u):
return Shopkeeper.objects.filter(user=u).exists()
actual_decorator = user_passes_test(is_shopkeeper)
if function:
return actual_decorator(function)
else:
return actual_decorator
def customer_required(function=None):
def is_customer(u):
return Customer.objects.filter(user=u).exists()
actual_decorator = user_passes_test(is_customer)
if function:
return actual_decorator(function)
else:
return actual_decorator
Вы можете, например, реализовать его как:
@login_required
@shopkeeper_required
def some_shopkeeper_view(request):
# ...
pass
@login_required
@customer_required
def some_customer_view(request):
# ...
pass
Обратите внимание, что это @shopkeeper_required
делает не действительно принудительно, что пользователь вошел в систему, хотя во многих случаях это будет так.
EDIT :
Мы можем объединить это с @login_required
(добавив параметр, который действует как переключатель для включения или выключения этого поведения по умолчанию), например:
from django.contrib.auth.decorators import user_passes_test
def shopkeeper_required(function=None<b>, login_required=True</b>, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
def is_shopkeeper(u):
<b>if login_required and not u.is_authenticated:
return False</b>
return Shopkeeper.objects.filter(user=u).exists()
actual_decorator = user_passes_test(
is_shopkeeper,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
else:
return actual_decorator
def customer_required(function=None<b>, login_required=True</b>, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
def is_customer(u):
<b>if login_required and not u.is_authenticated:
return False</b>
return Customer.objects.filter(user=u).exists()
actual_decorator = user_passes_test(
is_customer,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
else:
return actual_decorator