因此,我将在文档(link)中使用经典的Django Blog和Entry模型。我在条目的博客属性中添加了null=True
。Django - 了解RelatedManager删除方法
>>> 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
是要去回报None
,但我的问题是,为什么不gouda.blog
没有None
另一个查询?
编辑:
所以,如果我理解正确的一切,这是它如何工作的:
>>> 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>
的bulk
参数为remove()
方法,所以默认值是True
。这意味着将使用QuerySet.update()
。对象gouda
不会在Python级别更改,因此blog
属性仍将保留“Cheese博客”博客的主键。当我们查询gouda.blog
时,我们仍然会看到“Cheese blog”对象。
但bulk=False
传递给remove()
会发生什么?从文档:如果bulk = False,则调用每个单独模型实例的save()方法。
于是我重写Entry
模式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>
现在我们看到gouda
对象save()
方法被调用的是不一样的作为我们的shell中的一个,所以我们的shell中的对象仍然在其blog
属性中包含“Cheese博客”的主键。当我们查询gouda.blog
的博客时,我们仍然收到“Cheese blog”对象。
这是否正确,如果是,为什么save()
不会调用与我们传递给remove()
的同一对象?