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.
在 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.