在更新之前评估查询集

Posted

技术标签:

【中文标题】在更新之前评估查询集【英文标题】:Evaluating a queryset prior to updating 【发布时间】:2014-07-23 19:38:13 【问题描述】:

我的模型存储标记为已读/未读的线程消息。当用户查看消息线程时,未读消息应显示为未读,然后在同一请求中标记为已读。

因为在模板中呈现查询集之前通常不会对其进行评估,因此我的理解是我需要按以下顺序执行此操作:

    评估消息查询集以将消息已读/未读状态保留在内存中 调用更新以将消息标记为已读 使用评估的查询集呈现模板

否则,更新将首先执行,当随后在模板中评估消息查询集时,所有消息将被错误地呈现为已被读取。

实现步骤 1 的正确方法是简单地在查询集上调用 list() 吗?

例如:

class ViewMessageThread(TemplateView):
    template_name = 'inbox/message_thread.html'

    def get_context_data(self, **kwargs):
        context = super(ViewMessageThread, self).get_context_data(**kwargs)
        thread = MessageThread.objects.get(pk=self.kwargs['thread_id'])
        context['messages'] = list(Message.objects.filter(thread=thread))  # evaluate
        Message.objects.filter(thread=thread).update(status='read')  # update
        return context

django docs 包含一个警告,不要以这种方式评估查询集,因为涉及到内存开销。我不希望消息线程包含大量消息,并且查询集将以一种或另一种方式评估(在视图中或在模板中)。

是否有不同的首选方法来处理此问题?或者这样可以吗?

谢谢!

【问题讨论】:

【参考方案1】:

我认为这很好,但我会改变一件事:你执行过滤器两次。我会这样做:

_query = Message.objects.filter(thread=thread)
context['messages'] = list(_query)
_query.update(status='read')
return context

【讨论】:

不正确的提议,因为只有一小部分表达式是相同的,在list(queryset)评估之前没有将任何东西编译到SQL,执行的东西就越少。命令...update(...) 被编译成一个完全不同的SQL:UPDATE "yourapp_message" SET "status" = 'read' WHERE "yourapp_message"."thread_id" = %s,没有什么可以幸免的。是的,tino 的方法是最好的。

以上是关于在更新之前评估查询集的主要内容,如果未能解决你的问题,请参考以下文章

使用 ADODB 记录集执行联合更新​​查询

使用 ORM Django 过滤新更新的查询集返回空查询集

使用更新的参数集无法从 VB 关闭或刷新访问报表

按特定顺序更新查询集

如果存储过程在 SQL Server 2005 上的选择之前进行更新,则没有结果集

访问选择查询记录集不可更新