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

Django cascade delete doesn't remove pk of referenced model instance

在 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 以便它与数据库同步?

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

这是预期的行为。一旦 Django 从数据库中获取了某些内容(在本例中为 n1),直到您再次获取它(使用 Note.objects.get(pk=4)n1.refresh_from_db() 时,它才会知道对它的更改。

当您调用 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.