使用带有Django基于类的通用视图的ETag / Last-Modified装饰器

时间:2012-10-21 00:42:29

标签: python django http etag

我最近将我的一个Django项目中的所有视图迁移到新的基于类的视图中。对于经典的基于函数的Django视图,有一个方便的装饰器django.views.decorators.http.condition,如果有一个与您指定的条件匹配的缓存副本,它可用于绕过整个视图处理。我在文档和源代码中到处搜索,但是对于新的基于类的视图找不到任何实现。

所以我的问题是:您如何建议我为基于类的视图实现条件视图处理?

3 个答案:

答案 0 :(得分:4)

看起来这个问题还没有很好的答案。对于仅设置函数属性的装饰器(例如csrf_exempt),将它们应用于视图类的dispatch方法就足够了,但这显然不适用于condition装饰器,因为他们希望第一个函数参数是一个请求对象,而不是self

您可以通过两种方式实现这一目标:

  1. 将装饰器应用于生成的视图功能。通用视图功能实际上归结为一种从类构建视图函数的方法,因此应用装饰器可能是一种选择。像这样:

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

    这样做的缺点是您无法从传递给condition装饰器的函数中访问视图类。如果你在urlconf中调用as_view方法,也不是很方便。

  2. 委托一个简单的函数,您可以在视图的dispatch方法中应用装饰器。像这样:

    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)
    

    这个有一个好处,你可以在应用装饰器时访问视图类实例,因此你可以使用实例方法来实现缓存验证功能。缺点是每次调用视图时都会运行装饰器,但这对于这个特定的装饰器来说并不像是一个问题。

  3. 这两种解决方案都存在问题,所以也许值得提交一份错误报告,或者在django-users邮件列表上询问如何最好地结合这两个概念。

答案 1 :(得分:2)

您可以使用以下内容:

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))

答案 2 :(得分:1)

缓存是一个复杂的问题,但最近的趋势(服务器中的数据/片段缓存以及浏览器中的资产缓存)表明最好不要花时间解决缓存失效问题,而是只需执行本文中描述的内容:

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

应用于Django的这种技术的现实示例:

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