📜 ⬆️ ⬇️

“Verification Decorators” for Views

We talk about decorators


Each of us repeatedly used the login_required decorator and most likely wrote a similar decorator (say, to check if the basket is empty). Let's look at what this decorator is doing:



If you look at it entirely, you can think of it like this:


')
A decorator who checks the request that has come to him and, depending on the result, gives either a view or another function, we will call the check decorator.

Since the scheme is the same, we can write a “blank” for the decorator:

def check_decorator(view=None, condition_func = lambda request, *args, **kwargs: True, false_func = lambda request, *args, **kwargs: HttpResponse()): ''' Checks by :function:condition_func, if true go to :function: view, else go to :function:false_func :param condition_func: Should return Boolean value :type condition_func: function :param false_func: Should return object of :class:`http.HttpResponse' :return: :class:`http.HttpResponse` ''' def decorator(view): @wraps(view) def wrapper(request, *args, **kwargs): if not condition_func(request, *args, **kwargs): return false_func(request, *args, **kwargs) return view(request, *args, **kwargs) return wrapper return decorator(view) if view else decorator 


check_decorator is a basic function that accepts a view, a condition function (condition_func), and a function that is used with a negative result of the condition (false_func).

Now, to create a function that throws authorized users into a personal account (suppose from registration), we should take the following steps:
  1. Create check functions is_anonymous
  2. Create a function that will transfer to the office (office_redirect)
  3. C using functools.partial and our functions (is_anonymous, office_redirect) create a decorator


 from functools import partial is_anonymous = lambda request, *args, **kwargs: request.user.is_anonymous() office_redirect = lambda request, *args, **kwargs: redirect('office') # office -  view  urls should_be_anonymous = partial(check_decorator, condition_func=is_anonymous, false_func=office_redirect) 


I think that it’s not difficult for you to write another condition function or a function that is called when the condition is not passed (false_func).

And what about without redirect_url



Many of us are used to the fact that we can indicate where we will send the user by specifying redirect_url:

 @login_required(redirect_url=reverse_lazy('my_view_name')) def some_view(request, *args, **kwargs): pass 


In this case, our false_func function always produces a redirect, and we have to specify where to produce the url.
Let's create this function on the basis of our “stock”:

 def redirect_decorator(view=None, redirect_url=None, **kwargs): ''' Uses :function:`check_decorator` with false_func that returns :param:`redirect_url` ''' assert not redirect_url is None, "Redirect_url should be set" if 'false_handle_func' in kwargs: del kwargs['false_func'] redirect_func = lambda request, *args, **kwargs: redirect(redirect_url) return check_decorator(view=view, false_func=redirect_func, **kwargs) 


In the function redirect_decorator, we check whether the redirect_url is transmitted to us, and if we have been passed
false_func - delete it. Then return the value of the check_decorator function.

The function should_be_anonymous can be rewritten as:
 should_be_anonymous = partial(redirect_decorator, condition_func=is_anonymous) 


And use in our usual form:
 @should_be_anonymous(redirect_url=reverse_lazy('office')) def some_view(request, *args, **kwargs): pass 


Send a message


Django has a great django.messages messaging engine with which we can send messages to our user.
Let's see how it works:
We write in view:
 from django.contrib import messages def view(request, *args, **kwargs): ... messages.info("Hello World!") #  p ... 


Show in the template:
 {% if messages %} <ul> {% for message in messages %} <li>{{ message }}</li> {% endfor %} </ul> {% endif %} 


With the help of this mechanism, we can notify the user why he did not hit a page.
Create a function that will redirect and transmit our message:

 def redirect_message_decorator(view=None, message=None, redirect_url=None, **kwargs): ''' Uses :function: c`check_decorator` with false_func thar returns :param:`redirect_url` ''' assert not redirect_url is None, "Redirect_url should be set" assert not message is None, "Message should be set" if 'false_func' in kwargs: del kwargs['false_func'] def redirect_func(request, *args, **kwargs): messages.info(request, message) return redirect(redirect_url) return check_decorator(view=view, false_func=redirect_func, **kwargs) 


The function should_be_anonymous with the message looks like this:

 should_be_anonymous = partial(redirect_message_decorator, condition_func=is_anonymous) 


And the use of this decorator:

 @should_be_anonymous(message=u'  ', redirect_url=reverse_lazy('office')) def some_view(request, *args, **kwargs): pass 

Conclusion


You can use this snippet to use a decorator with CBV.
The article is not very complicated, but for beginners, I hope it will be interesting.
Everyone enjoy learning / using / developing the wonderful django framework.

Source: https://habr.com/ru/post/145709/


All Articles