1
0
mirror of https://github.com/django/django.git synced 2025-04-12 19:42:20 +00:00

[1.11.x] Fixed #28298 -- Prevented a primary key alteration from adding a foreign key constraint if db_constraint=False.

Backport of fba0eaa5d60603721d7b4653e3efacbfb3613bd2 from master
This commit is contained in:
Josh Schneier 2017-06-11 20:05:54 -04:00 committed by Tim Graham
parent d50e0e6553
commit 7765d3ba9b
3 changed files with 39 additions and 5 deletions

View File

@ -774,7 +774,7 @@ class BaseDatabaseSchemaEditor(object):
# Rebuild FKs that pointed to us if we previously had to drop them
if old_field.primary_key and new_field.primary_key and old_type != new_type:
for rel in new_field.model._meta.related_objects:
if not rel.many_to_many:
if not rel.many_to_many and rel.field.db_constraint:
self.execute(self._create_fk_sql(rel.related_model, rel.field, "_fk"))
# Does it have check constraints we need to add?
if old_db_params['check'] != new_db_params['check'] and new_db_params['check']:

View File

@ -51,3 +51,6 @@ Bugfixes
1.11.1, casting was added in Python to avoid localization of numeric values
in Django templates, but this made some use cases more difficult. Casting is
now done in the template using the ``|stringformat:'s'`` filter.
* Prevented a primary key alteration from adding a foreign key constraint if
``db_constraint=False`` (:ticket:`28298`).

View File

@ -9,9 +9,9 @@ from django.db import (
from django.db.models import Model
from django.db.models.deletion import CASCADE, PROTECT
from django.db.models.fields import (
AutoField, BigIntegerField, BinaryField, BooleanField, CharField,
DateField, DateTimeField, IntegerField, PositiveIntegerField, SlugField,
TextField, TimeField,
AutoField, BigAutoField, BigIntegerField, BinaryField, BooleanField,
CharField, DateField, DateTimeField, IntegerField, PositiveIntegerField,
SlugField, TextField, TimeField,
)
from django.db.models.fields.related import (
ForeignKey, ForeignObject, ManyToManyField, OneToOneField,
@ -21,7 +21,7 @@ from django.db.transaction import TransactionManagementError, atomic
from django.test import (
TransactionTestCase, mock, skipIfDBFeature, skipUnlessDBFeature,
)
from django.test.utils import CaptureQueriesContext
from django.test.utils import CaptureQueriesContext, isolate_apps
from django.utils import timezone
from .fields import (
@ -287,6 +287,37 @@ class SchemaTests(TransactionTestCase):
editor.alter_field(Author, new_field2, new_field, strict=True)
self.assertForeignKeyNotExists(Author, 'tag_id', 'schema_tag')
@isolate_apps('schema')
def test_no_db_constraint_added_during_primary_key_change(self):
"""
When a primary key that's pointed to by a ForeignKey with
db_constraint=False is altered, a foreign key constraint isn't added.
"""
class Author(Model):
class Meta:
app_label = 'schema'
class BookWeak(Model):
author = ForeignKey(Author, CASCADE, db_constraint=False)
class Meta:
app_label = 'schema'
with connection.schema_editor() as editor:
editor.create_model(Author)
editor.create_model(BookWeak)
self.assertForeignKeyNotExists(BookWeak, 'author_id', 'schema_author')
old_field = Author._meta.get_field('id')
new_field = BigAutoField(primary_key=True)
new_field.model = Author
new_field.set_attributes_from_name('id')
# @isolate_apps() and inner models are needed to have the model
# relations populated, otherwise this doesn't act as a regression test.
self.assertEqual(len(new_field.model._meta.related_objects), 1)
with connection.schema_editor() as editor:
editor.alter_field(Author, old_field, new_field, strict=True)
self.assertForeignKeyNotExists(BookWeak, 'author_id', 'schema_author')
def _test_m2m_db_constraint(self, M2MFieldClass):
class LocalAuthorWithM2M(Model):
name = CharField(max_length=255)