Django了解RelatedManager移除方法

2024-05-14 19:32:34 发布

您现在位置:Python中文网/ 问答频道 /正文

所以这里我将使用经典的Django博客和文档中的条目模型(link)。我在条目的blog属性中添加了null=True。在

>>> cb = Blog.objects.get(name__startswith="Cheese")
>>> gouda = Entry.objects.get(headline__startswith="Gouda")
>>> cb.entry_set.all()
[<Entry: Gouda>, <Entry: Emmentaler>]
>>> cb.entry_set.remove(gouda)
>>> gouda.blog
<Blog: Cheese blog>

我知道数据库中的一切都很好并且更新了,如果我再次查询示例中的第二行,gouda.blog将返回{},但我的问题是,为什么没有另一个查询,gouda.blog就不是{}?在

编辑:

所以,如果我对每件事都理解正确,这就是它的工作原理:

>>> cb = Blog.objects.get(name__startswith="Cheese")
>>> gouda = Entry.objects.get(headline__startswith="Gouda")
>>> cb.entry_set.all()
[<Entry: Gouda>, <Entry: Emmentaler>]
>>> cb.entry_set.remove(gouda)
>>> gouda.blog
<Blog: Cheese blog>

所以remove()方法的bulk参数的默认值是True。这意味着将使用QuerySet.update()。对象gouda不会在Python级别更改,因此blog属性仍将保留“Cheese blog”博客的主键。当我们查询gouda.blog时,我们仍然会得到“Cheese blog”对象。在

但是当bulk=False被传递给remove()时会发生什么呢?来自文档:如果bulk=False,则调用每个单独模型实例的save()方法。在

然后我重写save()模型的save()方法,如下所示:

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    if self.blog == None:
        print(id(self))

然后:

>>> cb = Blog.objects.get(name__startswith="Cheese")
>>> gouda = Entry.objects.get(headline__startswith="Gouda")
>>> cb.entry_set.all()
[<Entry: Gouda>, <Entry: Emmentaler>]
>>> id(gouda)
139797518743592
>>> cb.entry_set.remove(gouda, bulk=False)
139797518745552
>>> gouda.blog
<Blog: Cheese blog>

现在我们看到,调用save()方法的gouda对象与shell中的对象不相同,因此shell中的对象在其blog属性中仍然保留“Cheese blog”的主键。当我们用gouda.blog查询blog时,我们仍然得到“Cheese blog”对象。在

这是正确的吗?如果是,为什么我们传递给remove()的同一个对象上没有调用{}?在


Tags: 对象getobjectssaveblogremovecbentry

热门问题