Django级联删除不会删除引用的模型实例

时间:2016-08-07 00:55:23

标签: django django-models django-1.9

在Django 1.9中,我有 models.py 中定义的相关对象,如下所示:

from django.db import models

class Course(models.Model):
    title = models.CharField(max_length=10)

class Note(models.Model):
    course = models.ForeignKey(Course)

当我删除Course时,我希望通过默认的级联行为删除所有相关的Note。我得到的是以下行为:

>>> from test1.models import Course, Note

#First, create a Course and associated Note
>>> c1 = Course()
>>> c1.save()
>>> n1 = Note(course=c1)
>>> n1.save()
>>> c1.pk
4
>>> n1.pk
4

#Next, delete the Course, and see if Note deletes too
>>> c1.delete()
(2, {'test1.Course': 1, 'test1.Note': 1})
>>> c1.pk
>>> n1.pk
1    #pk remains
>>> Note.objects.get(pk=4)
Traceback (most recent call last):
...    test1.models.DoesNotExist: Note matching query does not exist.

#Finally, try deleting the Note manually
>>> n1.delete()
(0, {'test1.Note': 0})
>>> n1.pk
>>> #finally the pk is gone!

似乎数据库已正确更新,但只有Course对象在本地更新,而Note对象则没有(即保持其pk)。

为什么会这样,我怎样才能获得Note以删除pk以便它与db同步?

额外信息:我需要此行为的原因是我在其他地方使用了if note.pk:这样的语句来检查给定的Note是否已保存在数据库中。不幸的是,这种级联删除方式使这些语句无效,因为即使删除了数据库条目,也存在pk。

1 个答案:

答案 0 :(得分:2)

这是预期的行为。一旦Django从数据库中获取了某些内容(在这种情况下为n1),在您再次获取它之前,它不会知道对它的更改(使用Note.objects.get(pk=4)n1.refresh_from_db()。< / p>

当您调用c1.delete()时,Django会从数据库中删除该行并清除对象上的pk。它还会删除设置为级联的数据库中的所有相关对象。但是,它无法知道其他已经实例化的对象正在引用该对象 - 它怎么可能?

这是一个相同行为的简单示例,没有外键:

# Fetch a Course
>>> c1 = Course.objects.get(pk=1)
# Fetch the same course again, but save it to a different variable
>>> c2 = Course.objects.get(pk=1)

请注意,您现在在数据库中有两个同一行的实例。现在:

# Delete c1
>>> c1.delete()

# c2 Hasn't changed... how could it? That would be magical.
>>> c2.pk
1

# but if you refresh c2 from the database... it isn't there
>>> c2.refresh_from_db()
DoesNotExist: Course matching query does not exist.