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

发布于 2024-08-14 14:05:15 字数 1032 浏览 4 评论 0原文

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

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() 时间仅被调用一次(当它第一次加载时)。

我认为这是故意的,旨在提高性能 - 然而,这意味着视频会在之前出现在网站的其他位置(在我不在 object_detail 视图中的地方)它们在 object_detail 视图中可用(请参阅下面的 urls.py)。这会导致 404...

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

谢谢!

urls.py

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

I have a custom model manager that looks like this:

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

And this works well enough; however, I have a problem using Django's generic.list_detail views object_detail and object_list: the queryset seems to be only loading once and, because of this, it isn't fetching the items it should be because, I assume, the utcnow() time has been called only once (when it first loaded).

I assume this is intentional and meant as a performance boost - however, it means that video's show up elsewhere on the site (in places I am not in a object_detail view) before they are available in an object_detail view (see urls.py below). This is leading to 404s ...

Any ideas ? Or do I have to write my own custom views to avoid this ?

Thanks!

urls.py

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

如梦初醒的夏天 2024-08-21 14:05:15

这不是缓存的问题:正如您现在所做的那样,查询集定义在解析url时被评估一次,然后,它就不再被评估。

解决方案实际上非常简单,并在在线文档中进行了描述: 使用包装函数进行复杂过滤:只需创建一个小的自定义视图,它将简单地调用通用视图。
我实际上经常使用类似的解决方案,而且我觉得它很舒服。

顺便说一句,一个小旁注,对于这种情况,我建议不要使用自定义管理器,而是返回正常的过滤。

It is not a problem of cache: as you do it now, the queryset definition is evaluated once, while parsing urls, and then, it is never evaluated again.

Solution is actually pretty simple and described in the online documentation: Complex filtering with wrapper functions: just create a small custom view, that will simply call the generic view.
I am actually using a similar solution quite a lot and I feel it quite comfortable.

By the way, a small side note, for this case I would suggest not using a custom manager, and go back instead on a normal filtering.

送舟行 2024-08-21 14:05:15

尝试将 urls.py 更正为:

url(r'^video/(?P<object_id>\d+)

编辑:

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

return queryset.filter(pub_date__lte=datetime.utcnow)
, list_detail.object_detail, { 'queryset': Video.objects.all, }, # here's the difference name='video_detail', )

编辑:

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

Try correcting urls.py to:

url(r'^video/(?P<object_id>\d+)

Edit:

If this fail, try apply similar technique(passing callable instead of calling it) to filter():

return queryset.filter(pub_date__lte=datetime.utcnow)
, list_detail.object_detail, { 'queryset': Video.objects.all, }, # here's the difference name='video_detail', )

Edit:

If this fail, try apply similar technique(passing callable instead of calling it) to filter():

酷遇一生 2024-08-21 14:05:15

我有一个与 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+)

...它也不起作用,我现在可以看到我一定非常绝望地认为它会:)

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

blog_posts = {
    'queryset': lazy_qs(),

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

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

django 文档应该修改以指出通用视图使用的查询集的限制(目前文档有一个特别的注释告诉你一切都会好起来的!)

, list_detail.object_detail, { 'queryset': qs(), }, name='video_detail', ),

...它也不起作用,我现在可以看到我一定非常绝望地认为它会:)

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

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

django 文档应该修改以指出通用视图使用的查询集的限制(目前文档有一个特别的注释告诉你一切都会好起来的!)

I have an almost identical model Manager to thornomad, and the same problem with generic views.

I have to point out that neither of the suggestions above work:

  • doing Video.objects.all without parentheses gives an error
  • doing queryset.filter(pub_date__lte=datetime.utcnow), again without the parentheses, does not give an error but does not fix the problem

I have also tried another way, which is to use a lambda to return the queryset, eg:

qs = lambda *x: Video.objects.all()
url(r'^video/(?P<object_id>\d+)

...it didn't work either and I can see now I must have been desperate to think it would :)

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

blog_posts = {
    'queryset': lazy_qs(),

...doesn't work either (gives an error) as utils.functional.lazy doesn't know how to convert the result to a QuerySet properly, as best I can tell.

I think Roberto's answer of wrapping the generic view is the only one that will help.

The django docs should be amended to point out the limitations of the queryset used by generic views (currently the docs have a special note to tell you everything will be okay!)

, list_detail.object_detail, { 'queryset': qs(), }, name='video_detail', ),

...it didn't work either and I can see now I must have been desperate to think it would :)

...doesn't work either (gives an error) as utils.functional.lazy doesn't know how to convert the result to a QuerySet properly, as best I can tell.

I think Roberto's answer of wrapping the generic view is the only one that will help.

The django docs should be amended to point out the limitations of the queryset used by generic views (currently the docs have a special note to tell you everything will be okay!)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文