Commit 6e87dacf authored by Luke Plant's avatar Luke Plant
Browse files

[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
parent 4124ef33
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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)
+16 −0
Original line number Diff line number Diff line
@@ -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
Original line number Diff line number Diff line
@@ -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):