[英]Django - Understanding RelatedManager remove method
So here I will be using classic Django Blog and Entry models from the documentation ( link ). 因此,在这里,我将使用文档( 链接 )中的经典Django Blog和Entry模型。 I added null=True
to the Entry's blog attribute. 我在条目的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>
I know that everything is fine and updated in database and if I query the second line from my example again that gouda.blog
is gonna return None
, but my question is why is gouda.blog
not None
without another query? 我知道一切都很好并且已在数据库中进行了更新,如果我再次从示例中查询第二行, gouda.blog
将返回None
,但是我的问题是为什么gouda.blog
在None
其他查询的情况下不是None
?
EDIT: 编辑:
So if I understand everything correctly, this is how it works: 因此,如果我正确理解所有内容,则它是这样工作的:
>>> 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>
So default value of the bulk
argument for the remove()
method is True
. 因此, remove()
方法的bulk
参数的默认值为True
。 That means that QuerySet.update()
will be used. 这意味着将使用QuerySet.update()
。 Object gouda
will not be altered at the Python level so the blog
attribute will still hold primary key of the "Cheese blog" blog. 对象gouda
不会在Python级别更改,因此blog
属性仍将保持“ Cheese Blog”博客的主键。 When we query gouda.blog
, we will still get the "Cheese blog" object. 当查询gouda.blog
,仍将获得“ Cheese blog”对象。
But what happens when bulk=False
is passed to remove()
? 但是,当bulk=False
传递给remove()
时会发生什么? From documentation: If bulk=False, the save() method of each individual model instance is called instead. 来自文档:如果bulk = False,则调用每个单独的模型实例的save()方法。
So then I override save()
method of the Entry
model like this: 因此,我像这样重写Entry
模型的save()
方法:
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.blog == None:
print(id(self))
and then: 接着:
>>> 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>
Now we see that gouda
object that save()
method is called on is not the same as the one in our shell, so our object in the shell still holds primary key of "Cheese blog" in its blog
attribute. 现在我们看到调用save()
方法的gouda
对象与我们的shell中的对象不同,因此我们在shell中的对象在其blog
属性中仍然拥有“ Cheese blog”的主键。 And when we query for the blog with gouda.blog
we still get "Cheese blog" object. 并且当我们使用gouda.blog
查询博客时,我们仍然会获得“ Cheese blog”对象。
Is that correct and if it is, why is save()
not called on the same object that we passed to remove()
? 是正确的吗?如果是,为什么不对传递给remove()
的同一对象调用save()
remove()
?
You've said it yourself, you need to go back to the database to get the new information. 您自己说过,您需要返回数据库以获取新信息。 The gouda
object doesn't automatically keep a link to its database row; gouda
对象不会自动保持指向其数据库行的链接; it only queries it when told to do so. 它仅在被告知这样做时才查询它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.