Django - 了解RelatedManager删除方法

时间:2016-09-19 22:12:21

标签: python django

所以在这里我将使用文档中的经典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()的同一个对象?

1 个答案:

答案 0 :(得分:1)

您自己说过,您需要返回数据库才能获取新信息。 gouda对象不会自动保留到其数据库行的链接;只有在被告知时才会查询它。