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

泪湿孤枕 提交于 2019-12-03 14:02:17

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.

You may use the following:

def conditional(**kwargs):
    '''A wrapper around :func:`django.views.decorators.http.condition` that
    works for methods (i.e. class-based views).

    '''
    from django.views.decorators.http import condition
    from django.utils.decorators import method_decorator
    return method_decorator(condition(**kwargs))

Caching is a complex matter, but recent trends (both for data-/fragment-caching in the server, and for asset caching, in browsers) show that it is better not to spend time in solving the cache invalidation problem, but just do what described in this article:

http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works

Real-world example of this technique applied to Django:

http://www.rossp.org/blog/2012/feb/29/fragment-caching/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!