简体   繁体   English

Django-了解RelatedManager删除方法

[英]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.blogNone其他查询的情况下不是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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM