Use login_required with vary_on_headers with generic view in Django
-
21-04-2021 - |
Question
I'm have a generic view where I use the login_required decorator in the urls.py file, like this:
(r'^my-url/$', login_required(ListView.as_view())),
Now, I would like to use the vary_on_headers decorator for this url, but I can't get it working.
I've tried:
(r'^my-url/$', vary_on_headers(login_required(ListView.as_view()),'HTTP_X_REQUESTED_WITH'))
but I got the following error during my tests:
response = self.client.get('/my-url/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
File "/lib/python2.6/site-packages/django/test/client.py", line 439, in get
response = super(Client, self).get(path, data=data, **extra)
File "/lib/python2.6/site-packages/django/test/client.py", line 241, in get
return self.request(**r)
File "/lib/python2.6/site-packages/django/core/handlers/base.py", line 178, in get_response
response = middleware_method(request, response)
File "/lib/python2.6/site-packages/django/middleware/common.py", line 94, in process_response
if response.status_code == 404:
AttributeError: 'function' object has no attribute 'status_code'
If I try:
(r'^my-url/$', login_required(vary_on_headers(MyProductsView.as_view(),'HTTP_X_REQUESTED_WITH'))),
but I get the following error now:
response = self.client.get('/my-url/', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
File "/lib/python2.6/site-packages/django/test/client.py", line 439, in get
response = super(Client, self).get(path, data=data, **extra)
File "/lib/python2.6/site-packages/django/test/client.py", line 241, in get
return self.request(**r)
File "/lib/python2.6/site-packages/django/core/handlers/base.py", line 178, in get_response
response = middleware_method(request, response)
File "/lib/python2.6/site-packages/django/contrib/sessions/middleware.py", line 26, in process_response
patch_vary_headers(response, ('Cookie',))
File "/lib/python2.6/site-packages/django/utils/cache.py", line 133, in patch_vary_headers
if response.has_header('Vary'):
AttributeError: 'function' object has no attribute 'has_header'
Any ideas on what could be happening and how to solve this problem?
Solution
You have mixed up the view function that you are decorating with the header arguments for the vary_on_headers
decorator.
Try the following:
(r'^my-url/$', vary_on_headers('X_REQUESTED_WITH')(login_required(ListView.as_view())),
Or, if you want to apply the decorators the other way around:
(r'^my-url/$', login_required(vary_on_headers('X_REQUESTED_WITH')(ListView.as_view())),
OTHER TIPS
If you have a custom view class (or base class), instead of decorating every call to as_view()
, you can use method_decorator
to decorate the get
method of your view, or even dispatch
:
from django.utils.decorators import method_decorator
@method_decorator(vary_on_headers('X-Requested-With'))
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(MyView, self).dispatch(*args, **kwargs)
You could also create a mixin that does that.