Django的list_details视图将查询集保存到内存(不更新)?

时间:2009-12-06 22:22:16

标签: django django-urls django-views django-queryset

我有一个自定义模型管理器,如下所示:

class MyManager(models.Manager)
    def get_query_set(self):
        '''Only get items that are 'approved' and have a `pub_date` that is in
        the past.  Ignore the rest.'''
        queryset = super(MyManager, self).get_query_set()
        queryset = queryset.filter(status__in=('a',))
        return queryset.filter(pub_date__lte=datetime.utcnow())

这很好用;但是,我在使用Django的generic.list_detail视图object_detailobject_list时遇到问题:查询集似乎只加载一次,因此,它不是'提取它应该是的项目因为,我认为,utcnow()时间只被调用一次(首次加载时)。

我认为这是故意的,并且意味着性能提升 - 但是,这意味着视频会显示在网站的其他位置(我在<{1}}视图中 的地方)之前它们位于object_detail视图中(请参阅下面的urls.py)。这导致404s ......

有什么想法吗?或者我是否必须编写自己的自定义视图以避免这种情况?

谢谢!

urls.py

object_detail

3 个答案:

答案 0 :(得分:4)

这不是缓存问题:正如您现在所做的那样,查询集定义会在解析网址时进行一次评估,然后再对其进行评估。

解决方案实际上非常简单,并在在线文档中进行了描述:Complex filtering with wrapper functions:只需创建一个小型自定义视图,即可调用通用视图。
我实际上使用了类似的解决方案,我觉得很舒服。

顺便说一下,在这种情况下,我会建议不要使用自定义管理器,然后返回正常过滤。

答案 1 :(得分:2)

尝试将urls.py更正为:

url(r'^video/(?P<object_id>\d+)$', 
    list_detail.object_detail,
    {   'queryset': Video.objects.all, }, # here's the difference
    name='video_detail',
)

修改

如果失败,请尝试应用类似的技术(传递callable而不是调用它)到filter():

return queryset.filter(pub_date__lte=datetime.utcnow)

答案 2 :(得分:1)

我有一个与thornomad几乎相同的模型管理器,以及与通用视图相同的问题。

我必须指出上述两项建议都不奏效:

  • 做没有括号的Video.objects.all会出错
  • 执行queryset.filter(pub_date__lte = datetime.utcnow),再次没有括号,不会给出错误但不能解决问题

我还尝试了另一种方法,即使用lambda返回查询集,例如:

qs = lambda *x: Video.objects.all()
url(r'^video/(?P<object_id>\d+)$', 
    list_detail.object_detail,
    {   'queryset': qs(), },
    name='video_detail',
),

......它也没有用,我现在可以看到我一定是绝望地认为它会:)

lazy_qs = lambda *x: lazy(Post.live_objects.all, QuerySet)

blog_posts = {
    'queryset': lazy_qs(),

...也不起作用(给出错误),因为utils.functional.lazy不知道如何正确地将结果转换为QuerySet,正如我所知道的那样。

我认为罗伯托对包装通用视图的回答是唯一有帮助的回答。

应该修改django文档以指出通用视图使用的查询集的局限性(目前文档有一个特殊说明,告诉你一切都会好的!)