Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ETag / Last-Modified decorators with Django's class-based generic views

I've recently migrated all views in one of my Django projects to the new class-based ones. For classic function-based Django views there's a handy decorator django.views.decorators.http.condition that can be used to bypass the whole view processing if there's a cached copy matching the conditions that you've specified. I've searched everywhere in the docs and in the source code but can't find any implementation of this for the new class-based views.

So my question is: How would you suggest that I implement conditional view processing for class-based views?

like image 639
jmagnusson Avatar asked Oct 21 '12 00:10

jmagnusson


People also ask

How do you use decorators in class-based view in Django?

To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class. The decorators will process a request in the order they are passed to the decorator.

How do you call class-based views in Django?

Asynchronous class-based viewsimport asyncio from django. http import HttpResponse from django. views import View class AsyncView(View): async def get(self, request, *args, **kwargs): # Perform io-blocking view logic using await, sleep for example.

Which view decorator module can be used to control content compression on a per view basis?

GZip compressionviews. decorators. gzip control content compression on a per-view basis. This decorator compresses content if the browser allows gzip compression.

What is CBV in Django?

Django has two types of views; function-based views (FBVs), and class-based views (CBVs). Django originally started out with only FBVs, but then added CBVs as a way to templatize functionality so that you didn't have to write boilerplate (i.e. the same code) code over and over again.


1 Answers

It looks like there isn't a nice answer to this problem yet. For decorators that just set function attributes (e.g. csrf_exempt), it is enough to apply them to the view class's dispatch method, but that obviously doesn't work for the condition decorator, since they expect the first function argument to be a request object rather than self.

Two ways you could achieve this include:

  1. Apply the decorator to the generated view function. The generic view functionality really boils down to a way of building view functions from classes, so applying the decorator late might be an option. Something like this:

    f = ViewClass.as_view()
    f = condition(...)(f)
    

    This has the disadvantage that you don't have access to the view class from the functions you pass to the condition decorator. It is also not very convenient if you're calling the as_view method in the urlconf.

  2. Delegate to a simple function you can apply decorators to inside your view's dispatch method. Something like this:

    def dispatch(self, request, *args, **kwargs):
        @condition(...)
        def _dispatch(request, *args, **kwargs):
            return super(ViewClass, self).dispatch(request, *args, **kwargs)
        return _dispatch(request, *args, **kwargs)
    

    This one has the benefit that you have access to the view class instance when applying the decorator, so you could use instance methods for your cache validation functions. A downside is that the decorator will be run every time the view is invoked, but that doesn't look like a problem for this particular decorator.

Both solutions have their problems though, so perhaps it would be worth filing a bug report or asking on the django-users mailing list about how these two concepts should best be combined.

like image 152
James Henstridge Avatar answered Sep 28 '22 16:09

James Henstridge