[PYTHON] If you write the View decorator in urls.py in Django, the list will be higher.

In Django, View decorators are usually written in views.py, but it is recommended to write this in urls.py for better listing.

Normal usage (specify decorator in views.py)

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
    :

Specify the decorator in urls.py

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)),
]

There was also such a thing

https://github.com/vorujack/decorate_url

It seems that you can also specify a decorator for include ().

Recommended Posts

If you write the View decorator in urls.py in Django, the list will be higher.
If you remove the list to be looped, you will get terrible.
[Django 2.2] How do you display relation destinations in Django? [List View]
If you add sudo on ubuntu, it will be called the default python.
You will be an engineer in 100 days --Day 29 --Python --Basics of the Python language 5
You will be an engineer in 100 days --Day 33 --Python --Basics of the Python language 8
You will be an engineer in 100 days --Day 26 --Python --Basics of the Python language 3
If you change your password in Django, you'll be logged out without permission
You will be an engineer in 100 days --Day 32 --Python --Basics of the Python language 7
If an exception occurs in the function, it will be transmitted to the caller 2
If an exception occurs in the function, it will be transmitted to the caller 1
I didn't have to write a decorator in the class Thank you contextmanager
You will be an engineer in 100 days --Day 28 --Python --Basics of the Python language 4
Specify the view URL in your Django template
[Django] css in the project cannot be read
Write decorator in class
You will be an engineer in 100 days --Day 63 --Programming --Probability 1
How to write custom validations in the Django REST Framework
You will be an engineer in 100 days --Day 27 --Python --Python Exercise 1
You will be an engineer in 100 days --Day 65 --Programming --Probability 3
You will be an engineer in 100 days --Day 64 --Programming --Probability 2
You will be an engineer in 100 days --Day 34 --Python --Python Exercise 3
If __name__ == Raise your hand, if you write the code under'__main__'
You will be an engineer in 100 days --Day 31 --Python --Python Exercise 2
What to do if you get angry with'vertices' must be a 2D list ... in matplotlib arrow
If you write go table driven test in python, it may be better to use subTest