所以在这里我将使用文档中的经典Django Blog和Entry模型(link)。我在条目的博客属性中添加了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
将返回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 blog”博客的主键。当我们查询gouda.blog
时,我们仍会获得“奶酪博客”对象。
但是bulk=False
传递给remove()
时会发生什么?从文档:如果bulk = False,则调用每个单独模型实例的save()方法。
然后我覆盖save()
模型的Entry
方法,如下所示:
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中的对象仍保留着“Cheese blog”的主键。其blog
属性。当我们用gouda.blog
查询博客时,我们仍然会收到“奶酪博客”对象。
这是否正确,如果是,为什么save()
没有调用我们传递给remove()
的同一个对象?
答案 0 :(得分:1)
您自己说过,您需要返回数据库才能获取新信息。 gouda
对象不会自动保留到其数据库行的链接;只有在被告知时才会查询它。