Django:在上下文中传递模型后更改模型

Django:在上下文中传递模型后更改模型,django,Django,查看时我正在更改字段值列表,但我希望将未更改的值传递给上下文。这里的情况是原始通知系统,在查看通知时,它应将其状态更改为“已查看” views.py class Notification(TemplateView): template_name='myapp/notification.html' def get_context_data(self, **kwargs): user = self.request.user user_unread = user.notificat

查看时我正在更改字段值列表,但我希望将未更改的值传递给上下文。这里的情况是原始通知系统,在查看通知时,它应将其状态更改为“已查看”

views.py

class Notification(TemplateView):

template_name='myapp/notification.html'

def get_context_data(self, **kwargs):
    user = self.request.user
    user_unread = user.notification_set.filter(viewed=False)
    user_read = user.notification_set.filter(viewed=True)
    context = super(Notification, self).get_context_data(**kwargs)
    context.update({'user_unread': user_unread, 'user_read': user_read})
    for msg in user_unread:
        msg.viewed = True
        msg.save()
    return context
但是,这段代码的问题是,我在已读和未读列表中获得了重复的值,即使我在更新传递给模板的上下文后已将新值保存到模型中

模板:

Unread: 
<ul>
{% for msg in user_unread %}
    <li> {{ msg }} </li>
{% endfor %}
</ul>

Already read: 

<ul>
{% for msg in user_read %}
    <li> {{ msg }} </li>
{% endfor %}
</ul>
未读:
    {用户中的msg为%u未读%}
  • {{msg}}
  • {%endfor%}
已阅读:
    {用户_read%}中的msg为%
  • {{msg}}
  • {%endfor%}

另一方面,我是CBV新手,如果上面的视图代码可以改进的话,我希望有一些指针。

这是由于查询集的惰性。查询集在您对数据库求值之前不会实际接触数据库,这通常发生在您迭代时。因此,在您的代码中,您迭代视图中的
user\u unread
,以设置读取状态:因此查询集的内容在该点是固定的。但是,在到达模板之前,您不会遍历
user\u read
,因此在更新所有未读通知之前,不会进行查询

解决此问题的方法是在更新未读查询集之前,在视图中显式计算已读查询集。您只需在其上调用
list
即可:

context.update({'user_unread': user_unread, 'user_read': list(user_read)})
for msg in user_unread:
    ...

您可以尝试获取另一个重复查询集以更新对象。使用未更新的模板上下文,并仅更新另一个模板上下文

比如:

Django会对每个查询集进行不同的缓存。因此,一旦评估
用户\u未读
将拥有自己的对象副本


虽然,由于加载了类似查询集的多个副本,因此它不是非常优雅/高效,因此如果记录数太多,它将变慢。

不,这将不起作用,原因完全相同:查询集在更新完成后才会计算,因此消息将始终显示为已读。@DanielRoseman,我已经提到了这一点,并且评估了QS
len(user\u unread)
,以便在获得它之后,对它进行评估。啊,对不起,没有看到这一点。
def get_context_data(self, **kwargs):
    user = self.request.user
    user_unread = user.notification_set.filter(viewed=False)

    #Do some operation on qs so that it gets evaluated, like
    nitems = len(user_unread)

    #get another queryset to update
    user_unread_toupdate = user.notification_set.filter(viewed=False)

    user_read = user.notification_set.filter(viewed=True)
    context = super(Notification, self).get_context_data(**kwargs)
    context.update({'user_unread': user_unread, 'user_read': user_read})

    #Use 2nd queryset
    for msg in user_unread_toupdate:
        msg.viewed = True
        msg.save()
    return context