From e01cb0740496f12323260205687111a54a91e10f Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Wed, 19 Jan 2011 21:56:14 +0000 Subject: [PATCH] Fixed #14896 -- Ensured that _meta.get_all_related_objects(include_hidden=True) also works correctly with model inheritance. git-svn-id: http://code.djangoproject.com/svn/django/trunk@15248 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/options.py | 2 +- .../regressiontests/delete_regress/models.py | 9 ++++ tests/regressiontests/delete_regress/tests.py | 43 ++++++++++++------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/django/db/models/options.py b/django/db/models/options.py index a3697c2a13..882d2f5709 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -371,7 +371,7 @@ class Options(object): cache = SortedDict() parent_list = self.get_parent_list() for parent in self.parents: - for obj, model in parent._meta.get_all_related_objects_with_model(): + for obj, model in parent._meta.get_all_related_objects_with_model(include_hidden=True): if (obj.field.creation_counter < 0 or obj.field.rel.parent_link) and obj.model not in parent_list: continue if not model: diff --git a/tests/regressiontests/delete_regress/models.py b/tests/regressiontests/delete_regress/models.py index 8109c0a96b..07b58317ae 100644 --- a/tests/regressiontests/delete_regress/models.py +++ b/tests/regressiontests/delete_regress/models.py @@ -35,3 +35,12 @@ class PlayedWith(models.Model): class PlayedWithNote(models.Model): played = models.ForeignKey(PlayedWith) note = models.TextField() + +class Contact(models.Model): + label = models.CharField(max_length=100) + +class Email(Contact): + email_address = models.EmailField(max_length=100) + +class Researcher(models.Model): + contacts = models.ManyToManyField(Contact, related_name="research_contacts") diff --git a/tests/regressiontests/delete_regress/tests.py b/tests/regressiontests/delete_regress/tests.py index 754031b7af..7e243c841c 100644 --- a/tests/regressiontests/delete_regress/tests.py +++ b/tests/regressiontests/delete_regress/tests.py @@ -4,7 +4,8 @@ from django.conf import settings 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 +from models import (Book, Award, AwardNote, Person, Child, Toy, PlayedWith, + PlayedWithNote, Contact, Email, Researcher) # Can't run this test under SQLite, because you can't @@ -62,17 +63,12 @@ class DeleteLockingTest(TransactionTestCase): transaction.commit() self.assertEqual(1, Book.objects.count()) + class DeleteCascadeTests(TestCase): def test_generic_relation_cascade(self): """ - Test that Django cascades deletes through generic-related - objects to their reverse relations. - - This might falsely succeed if the database cascades deletes - itself immediately; the postgresql_psycopg2 backend does not - give such a false success because ForeignKeys are created with - DEFERRABLE INITIALLY DEFERRED, so its internal cascade is - delayed until transaction commit. + Django cascades deletes through generic-related objects to their + reverse relations. """ person = Person.objects.create(name='Nelson Mandela') @@ -87,13 +83,10 @@ class DeleteCascadeTests(TestCase): def test_fk_to_m2m_through(self): """ - Test that if a M2M relationship has an explicitly-specified - through model, and some other model has an FK to that through - model, deletion is cascaded from one of the participants in - the M2M, to the through model, to its related model. - - Like the above test, this could in theory falsely succeed if - the DB cascades deletes itself immediately. + If an M2M relationship has an explicitly-specified through model, and + some other model has an FK to that through model, deletion is cascaded + from one of the participants in the M2M, to the through model, to its + related model. """ juan = Child.objects.create(name='Juan') @@ -108,6 +101,24 @@ class DeleteCascadeTests(TestCase): # first two asserts just sanity checks, this is the kicker: self.assertEquals(PlayedWithNote.objects.count(), 0) + +class DeleteCascadeTransactionTests(TransactionTestCase): + def test_inheritance(self): + """ + Auto-created many-to-many through tables referencing a parent model are + correctly found by the delete cascade when a child of that parent is + deleted. + + Refs #14896. + """ + r = Researcher.objects.create() + email = Email.objects.create( + label="office-email", email_address="carl@science.edu" + ) + r.contacts.add(email) + + email.delete() + class LargeDeleteTests(TestCase): def test_large_deletes(self): "Regression for #13309 -- if the number of objects > chunk size, deletion still occurs"