Skip to content

Commit fba0eaa

Browse files
jschneiertimgraham
authored andcommitted
Fixed #28298 -- Prevented a primary key alteration from adding a foreign key constraint if db_constraint=False.
1 parent 0af14b2 commit fba0eaa

File tree

3 files changed

+36
-2
lines changed

3 files changed

+36
-2
lines changed

django/db/backends/base/schema.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ def _alter_field(self, model, old_field, new_field, old_type, new_type,
727727
# Rebuild FKs that pointed to us if we previously had to drop them
728728
if old_field.primary_key and new_field.primary_key and old_type != new_type:
729729
for rel in new_field.model._meta.related_objects:
730-
if not rel.many_to_many:
730+
if not rel.many_to_many and rel.field.db_constraint:
731731
self.execute(self._create_fk_sql(rel.related_model, rel.field, "_fk"))
732732
# Does it have check constraints we need to add?
733733
if old_db_params['check'] != new_db_params['check'] and new_db_params['check']:

docs/releases/1.11.3.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,6 @@ Bugfixes
5151
1.11.1, casting was added in Python to avoid localization of numeric values
5252
in Django templates, but this made some use cases more difficult. Casting is
5353
now done in the template using the ``|stringformat:'s'`` filter.
54+
55+
* Prevented a primary key alteration from adding a foreign key constraint if
56+
``db_constraint=False`` (:ticket:`28298`).

tests/schema/tests.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from django.test import (
2323
TransactionTestCase, skipIfDBFeature, skipUnlessDBFeature,
2424
)
25-
from django.test.utils import CaptureQueriesContext
25+
from django.test.utils import CaptureQueriesContext, isolate_apps
2626
from django.utils import timezone
2727

2828
from .fields import (
@@ -319,6 +319,37 @@ def test_fk_db_constraint(self):
319319
editor.alter_field(Author, new_field2, new_field, strict=True)
320320
self.assertForeignKeyNotExists(Author, 'tag_id', 'schema_tag')
321321

322+
@isolate_apps('schema')
323+
def test_no_db_constraint_added_during_primary_key_change(self):
324+
"""
325+
When a primary key that's pointed to by a ForeignKey with
326+
db_constraint=False is altered, a foreign key constraint isn't added.
327+
"""
328+
class Author(Model):
329+
class Meta:
330+
app_label = 'schema'
331+
332+
class BookWeak(Model):
333+
author = ForeignKey(Author, CASCADE, db_constraint=False)
334+
335+
class Meta:
336+
app_label = 'schema'
337+
338+
with connection.schema_editor() as editor:
339+
editor.create_model(Author)
340+
editor.create_model(BookWeak)
341+
self.assertForeignKeyNotExists(BookWeak, 'author_id', 'schema_author')
342+
old_field = Author._meta.get_field('id')
343+
new_field = BigAutoField(primary_key=True)
344+
new_field.model = Author
345+
new_field.set_attributes_from_name('id')
346+
# @isolate_apps() and inner models are needed to have the model
347+
# relations populated, otherwise this doesn't act as a regression test.
348+
self.assertEqual(len(new_field.model._meta.related_objects), 1)
349+
with connection.schema_editor() as editor:
350+
editor.alter_field(Author, old_field, new_field, strict=True)
351+
self.assertForeignKeyNotExists(BookWeak, 'author_id', 'schema_author')
352+
322353
def _test_m2m_db_constraint(self, M2MFieldClass):
323354
class LocalAuthorWithM2M(Model):
324355
name = CharField(max_length=255)

0 commit comments

Comments
 (0)