[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:
parent
4124ef339c
commit
6e87dacf62
|
@ -83,8 +83,8 @@ class Collector(object):
|
||||||
def add(self, objs, source=None, nullable=False, reverse_dependency=False):
|
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
|
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
|
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.
|
and 'nullable' should be set to True if the relation can be null.
|
||||||
|
|
||||||
Returns a list of all objects that were not already collected.
|
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
|
# Nullable relationships can be ignored -- they are nulled out before
|
||||||
# deleting, and therefore do not affect the order in which objects have
|
# deleting, and therefore do not affect the order in which objects have
|
||||||
# to be deleted.
|
# 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:
|
if reverse_dependency:
|
||||||
source, model = model, source
|
source, model = model, source
|
||||||
self.dependencies.setdefault(source, set()).add(model)
|
self.dependencies.setdefault(source, set()).add(model)
|
||||||
|
|
|
@ -51,3 +51,19 @@ class Food(models.Model):
|
||||||
class Eaten(models.Model):
|
class Eaten(models.Model):
|
||||||
food = models.ForeignKey(Food, to_field="name")
|
food = models.ForeignKey(Food, to_field="name")
|
||||||
meal = models.CharField(max_length=20)
|
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)
|
||||||
|
|
|
@ -5,7 +5,8 @@ from django.db import backend, connection, transaction, DEFAULT_DB_ALIAS
|
||||||
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
|
from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
from models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith,
|
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
|
# 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:
|
# first two asserts just sanity checks, this is the kicker:
|
||||||
self.assertEqual(PlayedWithNote.objects.count(), 0)
|
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):
|
class DeleteCascadeTransactionTests(TransactionTestCase):
|
||||||
def test_inheritance(self):
|
def test_inheritance(self):
|
||||||
|
|
Loading…
Reference in New Issue