【问题标题】:Using ETag / Last-Modified decorators with Django's class-based generic views将 ETag / Last-Modified 装饰器与 Django 基于类的通用视图一起使用
【发布时间】:2012-10-21 00:42:28
【问题描述】:

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

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

【问题讨论】:

    标签: python django http etag


    【解决方案1】:

    看起来这个问题还没有很好的答案。对于只设置函数属性的装饰器(例如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)
      

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

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

    【讨论】:

    • 我实际上最终缓存了网站上的所有内容,因为它的阅读量很大,管理员每周只编辑几次。当某些事情发生变化时,我会清除整个缓存并让“缓存机器人”重新访问最常用的页面。
    • 技术 2 也适用于 Django Syndication 框架,只需覆盖 __call__ 而不是 dispatch
    【解决方案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))
    

    【讨论】:

    • 如果您查看method_decorator,您会发现这与詹姆斯描述的第二个选项基本相同。
    【解决方案3】:

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

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

    此技术应用于 Django 的真实示例:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-08
      • 2023-02-07
      • 2014-07-23
      • 2011-08-29
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多