6 лучших декораторов Django
Перевод: Pablo Iglesias — Top 6 Django Decorators
Что такое декоратор?
Декоратор — это название одного из самых популярных шаблонов проектирования, используемых в настоящее время, хотя часто мы используем его, не зная, что это именно шаблон проектирования. А что такого особенного в этом шаблоне? Как мы можем прочитать в Python Wiki, это способ явно изменить поведение объекта, заключив его в декорируемый объект с аналогичным интерфейсом. Вы можете почитать больше о дизайне паттернов здесь.
Почему я должен использовать декораторы в своем веб-приложении?
Декораторы динамически изменяют функциональность функции, метода или класса без необходимости создавать подклассы или изменять исходный код декорированного класса. Благодаря этому наш код будет более чистым, более читаемым, удобным в обслуживании (что немаловажно), что позволит нам добавлять функциональность к нескольким классам с помощью одного метода.
Хороший пример важности и простоты использования этих декораторов можно увидеть в декораторе @login_required, который предоставляет django, и который вы, вероятно, использовали, если у вас есть некоторый опыт работы с нашим любимым фреймворком. Это всего лишь фрагмент кода, в котором мы проверяем, аутентифицирован ли пользователь, и перенаправляем его если нет на URL-адрес логирования.
Декораторы используются следующим образом:
from django.contrib.auth.decorators import login_required @login_required def my_view(request) …
Каждый раз, когда пользователь пытается получить доступ к my_view, запускается код внутри login_required.
Некоторые из наших любимых декораторов
В этой статье мы расскажем о некоторых декораторах, которые мы считаем наиболее полезными или которые мы когда-либо использовали с положительными результатами, имейте в виду, что многие из них можно настроить в соответствии с вашими потребностями.
Group Required
Иногда нам нужно защитить некоторые представления, чтобы позволить определенной группе пользователей получить к ним доступ. Вместо того, чтобы проверять, принадлежит ли пользователь к этой группе/группам, мы можем использовать следующий декоратор
from django.contrib.auth.decorators import user_passes_test def group_required(*group_names): """Requires user membership in at least one of the groups passed in.""" def in_groups(u): if u.is_authenticated(): if bool(u.groups.filter(name__in=group_names)) | u.is_superuser: return True return False return user_passes_test(in_groups) # The way to use this decorator is: @group_required(‘admins’, ‘seller’) def my_view(request, pk) ...
Вы можете прочитать о нем более подробно здесь.
Anonymous required
Этот декоратор основан на декораторе login_required Django, но используется в противоположном случае, когда пользователь является анонимным, в противном случае пользователь перенаправляется на веб-сайт, определенный в нашем settings.py, и может быть полезен, когда мы хотим защитить зарегистрированные просмотры пользователей. , например, вьюхи логирования или регистрации
def anonymous_required(function=None, redirect_url=None): if not redirect_url: redirect_url = settings.LOGIN_REDIRECT_URL actual_decorator = user_passes_test( lambda u: u.is_anonymous(), login_url=redirect_url ) if function: return actual_decorator(function) return actual_decorator # The way to use this decorator is: @anonymous_required def my_view(request, pk) ...
Вы можете почитать о нем здесь.
Superuser required
Это тот же случай, когда мы хотим разрешить определенным группам доступ к представлению, но в этом случае только суперпользователи могут посещать его.
from django.core.exceptions import PermissionDenied def superuser_only(function): """Limit view to superusers only.""" def _inner(request, *args, **kwargs): if not request.user.is_superuser: raise PermissionDenied return function(request, *args, **kwargs) return _inner # The way to use this decorator is: @superuser_only def my_view(request): ...
Вы можете почитать более подробно здесь.
Ajax required
Этот декоратор проверяет, является ли запрос запросом AJAX. Этот декоратор, используется когда мы работаем с Javascript фреймворками такими как jQuery.
from django.http import HttpResponseBadRequest def ajax_required(f): """ AJAX request required decorator use it in your views: @ajax_required def my_view(request): .... """ def wrap(request, *args, **kwargs): if not request.is_ajax(): return HttpResponseBadRequest() return f(request, *args, **kwargs) wrap.__doc__=f.__doc__ wrap.__name__=f.__name__ return wrap # The way to use this decorator is: @ajax_required def my_view(request): ...
Вы можете почитать более подробно здесь.
Time it
Этот декоратор очень полезен, если вам нужно улучшить время отклика одного из наших представлений или если вы просто хотите знать, сколько времени требуется для его выполнения.
def timeit(method): def timed(*args, **kw): ts = time.time() result = method(*args, **kw) te = time.time() print('%r (%r, %r) %2.2f sec' % (method.__name__, args, kw, te - ts)) return result return timed # The way to use this decorator is: @timeit def my_view(request): ...
Вы можете почитать более подробно здесь.
Пользовательские функции
Следующий декоратор — это просто пример того, как вы можете легко и на 100% настраивать некоторые разрешения или проверки.
Представьте, что у вас есть блог, магазин, форум … Если пользователям нужно набрать определенное количество баллов, чтобы написать отзыв, например, что бы избежать спама. Мы создадим декоратор, чтобы проверить, что пользователь вошел в систему и набрал более 10 баллов, чтобы он мог написать отзыв, в противном случае мы поднимем Forbidden
from django.http import HttpResponseForbidden logger = logging.getLogger(__name__) def user_can_write_a_review(func): """View decorator that checks a user is allowed to write a review, in negative case the decorator return Forbidden""" @functools.wraps(func) def wrapper(request, *args, **kwargs): if request.user.is_authenticated() and request.user.points < 10: logger.warning('The {} user has tried to write a review, but does not have enough points to do so'.format( request.user.pk)) return HttpResponseForbidden() return func(request, *args, **kwargs) return wrapper
Вы можете получить дополнительную информацию об этом, спросив меня, по адресу piglesias@emergya.com или через twitter @pypiglesias. Я очень надеюсь, что вы нашли этот пост интересным или, по крайней мере, любопытным. В BeDjango мы хотели бы предложить вам поделиться своими декораторами, идеями или вопросами, а также интересными темами для будущих публикаций.