Before class-based views, decorators were the only way to change the behavior of function-based views. Being wrappers around a function, they cannot change the inner working of the view, and thus effectively treat them as black boxes.
A decorator is a function that takes a function and returns the decorated function. Confused? There is some syntactic sugar to help you. Use the annotation notation @, as shown in the following login_required decorator example:
@login_required def simple_view(request): return HttpResponse()
The following code is exactly the same as the preceding:
def simple_view(request): return HttpResponse() simple_view = login_required(simple_view)
Since login_required wraps around the view, a wrapper function gets the control first. If the user was not logged-in, then it redirects to settings.LOGIN_URL. Otherwise, it executes simple_view...