In Django, View decorators are usually written in views.py, but it is recommended to write this in urls.py for better listing.
If there are multiple views and the implementation of each view becomes large, it becomes difficult to check which decorator is specified for which view.
views.py
def view1(request):
:
#Long processing
:
@login_required
@staff_member_required
def view2(request):
:
#Long processing
:
@login_required
@has_permission('xxx')
def view3(request):
:
#Long processing
:
@login_required
@has_permission('xxx')
def view4(request):
:
#Long processing
:
Since urls.py basically only writes one line of code for one View, it seems that the list will be high if you can specify the decorator here. To specify a decorator in urls.py, write:
urls.py
urlpatterns = [
url(r'^$', login_required(has_permission('xxx')(views.view4)))
]
If this is left as it is, it will be nested and difficult to read when using multiple decorators, so create and use a function for specifying decorators.
urls.py
def decorate(view_func, decorators):
for decorator in reversed(decorators):
view_func = decorator(view_func)
urlpatterns = [
url(r'^$', decorete(views.view4, [login_required, has_permission('xxx')]))
]
Furthermore, since the same combination is often used to specify the decorator, these patterns are defined as constants.
python
#Accessable without login
PUBLIC = []
#Only accessible to people inside
STAFF_ONLY = [
login_required,
staff_member_required,
]
#Only accessible to people with permission xxx
XXX = [
login_required,
has_permission('xxx'),
]
This makes it easier to check the specifications of each View.
urls.py
urlpatterns = [
url(r'^view1/$', decorate(views.view1, PUBLIC)),
url(r'^view2/$', decorate(views.view1, STAFF_ONLY)),
url(r'^view3/$', decorate(views.view2, XXX)),
url(r'^view4/$', decorate(views.view3, XXX)),
]
https://github.com/vorujack/decorate_url
It seems that you can also specify a decorator for include ().
Recommended Posts