2016-09-19 81 views
0

因此,我将在文档(link)中使用经典的Django Blog和Entry模型。我在条目的博客属性中添加了null=TrueDjango - 了解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()的同一对象?

回答

1

你已经说过了,你需要回到数据库来获取新的信息。 gouda对象不会自动保留到其数据库行的链接;它只会在被告知时这样做。