Django';s列表\u详细信息视图是否将查询集保存到内存(不更新)?
我有一个自定义模型管理器,如下所示:Django';s列表\u详细信息视图是否将查询集保存到内存(不更新)?,django,django-urls,django-views,django-queryset,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_
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_detail
和object_list
时遇到了一个问题:queryset似乎只加载了一次,因此,它没有获取应该是的项,因为我假设utcnow()
时间只被调用了一次(当它第一次加载时)
我认为这是有意的,是为了提高性能-但是,这意味着视频在对象详细信息视图中可用之前,会显示在站点的其他位置(在我不在对象详细信息视图中的位置)。这将导致404
有什么想法吗?或者我必须编写自己的自定义视图来避免这种情况
谢谢
url.py
url(r'^video/(?P\d+)$”,
列出详细信息。对象详细信息,
{'queryset':Video.objects.all(),},
name='video\u detail',
),
尝试将URL.py更正为:
url(r'^video/(?P<object_id>\d+)$',
list_detail.object_detail,
{ 'queryset': Video.objects.all, }, # here's the difference
name='video_detail',
)
这不是缓存的问题:正如您现在所做的那样,queryset定义在解析URL时只计算一次,然后再也不会计算
解决方案实际上非常简单,并在联机文档中进行了描述::只需创建一个小的自定义视图,它将简单地调用通用视图。
事实上,我经常使用类似的解决方案,我觉得很舒服
顺便说一句,在这种情况下,我建议不要使用自定义管理器,而是使用常规筛选。我的模型管理器与thornomad几乎相同,而通用视图也存在同样的问题
我必须指出,上述两项建议都不起作用:
- 如果不使用括号执行Video.objects.all,则会出现错误
- 执行queryset.filter(pub\u date\u lte=datetime.utcnow),同样不带括号,不会给出错误,但不会修复问题
我还尝试了另一种方法,即使用lambda返回queryset,例如:
qs = lambda *x: Video.objects.all()
url(r'^video/(?P<object_id>\d+)$',
list_detail.object_detail,
{ 'queryset': qs(), },
name='video_detail',
),
…也不起作用(给出一个错误),因为utils.functional.lazy不知道如何正确地将结果转换为查询集,这是我所知道的
我认为Roberto关于包装通用视图的回答是唯一有帮助的
django文档应该被修改,以指出泛型视图所使用的queryset的局限性(目前文档有一个特别的注释,告诉您一切都会好起来的!)我已经尝试过了,但是获取一个'function'对象没有属性'model'
错误-因为列表\u detail
查看克隆的it…QuerySets是惰性的(),在URL模式中调用all
或过滤器应该没有问题。这甚至在文档中的某个地方解释过,但我现在找不到。包装通用视图是一种很好的技术,但在这种情况下不需要。这里只需要从Video.objects.All中删除()即可。
return queryset.filter(pub_date__lte=datetime.utcnow)
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(),