我有一个自定义模型管理器,如下所示:
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
时遇到问题:查询集似乎只加载一次,因此,它不是'提取它应该是的项目因为,我认为,utcnow()
时间只被调用一次(首次加载时)。
我认为这是故意的,并且意味着性能提升 - 但是,这意味着视频会显示在网站的其他位置(我在<{1}}视图中 的地方)之前它们位于object_detail
视图中(请参阅下面的urls.py)。这导致404s ......
有什么想法吗?或者我是否必须编写自己的自定义视图以避免这种情况?
谢谢!
object_detail
答案 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几乎相同的模型管理器,以及与通用视图相同的问题。
我必须指出上述两项建议都不奏效:
我还尝试了另一种方法,即使用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文档以指出通用视图使用的查询集的局限性(目前文档有一个特殊说明,告诉你一切都会好的!)