[1.3.X] 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.

Backport of [16295] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.3.X@16296 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Luke Plant 2011-05-30 16:19:53 +00:00
parent 4124ef339c
commit 6e87dacf62
3 changed files with 28 additions and 4 deletions

View File

@ -83,8 +83,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.
"""
@ -100,7 +100,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)

View File

@ -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)

View File

@ -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):