Browse Source

Fixed #15776 - delete regression in Django 1.3 involving nullable foreign keys

Many thanks to aaron.l.madison for the detailed report and to emulbreh for
the fix.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16295 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Luke Plant 14 năm trước cách đây
mục cha
commit
de3b58d626

+ 3 - 3
django/db/models/deletion.py

@@ -82,8 +82,8 @@ class Collector(object):
     def add(self, objs, source=None, nullable=False, reverse_dependency=False):
         """
         Adds 'objs' to the collection of objects to be deleted.  If the call is
-        the result of a cascade, 'source' should be the model that caused it
-        and 'nullable' should be set to True, if the relation can be null.
+        the result of a cascade, 'source' should be the model that caused it,
+        and 'nullable' should be set to True if the relation can be null.
 
         Returns a list of all objects that were not already collected.
         """
@@ -99,7 +99,7 @@ class Collector(object):
         # Nullable relationships can be ignored -- they are nulled out before
         # deleting, and therefore do not affect the order in which objects have
         # to be deleted.
-        if new_objs and source is not None and not nullable:
+        if source is not None and not nullable:
             if reverse_dependency:
                 source, model = model, source
             self.dependencies.setdefault(source, set()).add(model)

+ 16 - 0
tests/regressiontests/delete_regress/models.py

@@ -51,3 +51,19 @@ class Food(models.Model):
 class Eaten(models.Model):
     food = models.ForeignKey(Food, to_field="name")
     meal = models.CharField(max_length=20)
+
+
+# Models for #15776
+
+class Policy(models.Model):
+    policy_number = models.CharField(max_length=10)
+
+class Version(models.Model):
+    policy = models.ForeignKey(Policy)
+
+class Location(models.Model):
+    version = models.ForeignKey(Version, blank=True, null=True)
+
+class Item(models.Model):
+    version = models.ForeignKey(Version)
+    location = models.ForeignKey(Location, blank=True, null=True)

+ 9 - 1
tests/regressiontests/delete_regress/tests.py

@@ -5,7 +5,8 @@ from django.db import backend, connection, transaction, DEFAULT_DB_ALIAS
 from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
 
 from models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith,
-    PlayedWithNote, Contact, Email, Researcher, Food, Eaten)
+    PlayedWithNote, Contact, Email, Researcher, Food, Eaten,
+    Policy, Version, Location, Item)
 
 
 # Can't run this test under SQLite, because you can't
@@ -102,6 +103,13 @@ class DeleteCascadeTests(TestCase):
         # first two asserts just sanity checks, this is the kicker:
         self.assertEqual(PlayedWithNote.objects.count(), 0)
 
+    def test_15776(self):
+        policy = Policy.objects.create(pk=1, policy_number="1234")
+        version = Version.objects.create(policy=policy)
+        location = Location.objects.create(version=version)
+        item = Item.objects.create(version=version, location=location)
+        policy.delete()
+
 
 class DeleteCascadeTransactionTests(TransactionTestCase):
     def test_inheritance(self):