From cd2fe829dddb4c8914ac62c93cd6d750a4e9c30c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Bogda=C5=82?= Date: Fri, 11 Nov 2016 02:38:16 +0100 Subject: [PATCH] Fixed #24195 -- Deconstructed the limit_choices_to option of related fields. Migrations will now be created for changes to limit_choices_to. --- AUTHORS | 1 + django/db/models/fields/related.py | 6 ++++++ docs/releases/2.0.txt | 4 ++++ tests/field_deconstruction/tests.py | 26 ++++++++++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/AUTHORS b/AUTHORS index 8a7e34d1e1..0da7f9e9d1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,6 +9,7 @@ answer newbie questions, and generally made Django that much better: Aaron Swartz Aaron T. Myers Abhishek Gautam + Adam BogdaƂ Adam Johnson Adam Malinowski Adam Vandenberg diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index f755355079..b01142f056 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -318,6 +318,12 @@ class RelatedField(Field): field.do_related_class(related, model) lazy_related_operation(resolve_related_class, cls, self.remote_field.model, field=self) + def deconstruct(self): + name, path, args, kwargs = super().deconstruct() + if self.remote_field.limit_choices_to: + kwargs['limit_choices_to'] = self.remote_field.limit_choices_to + return name, path, args, kwargs + def get_forward_related_filter(self, obj): """ Return the keyword arguments that when supplied to diff --git a/docs/releases/2.0.txt b/docs/releases/2.0.txt index 5214b3f2f5..dae5dab9fe 100644 --- a/docs/releases/2.0.txt +++ b/docs/releases/2.0.txt @@ -444,6 +444,10 @@ Miscellaneous * A model instance's primary key now appears in the default ``Model.__str__()`` method, e.g. ``Question object (1)``. +* ``makemigrations`` now detects changes to the model field ``limit_choices_to`` + option. Add this to your existing migrations or accept an auto-generated + migration for fields that use it. + .. _deprecated-features-2.0: Features deprecated in 2.0 diff --git a/tests/field_deconstruction/tests.py b/tests/field_deconstruction/tests.py index 7b816b8bf0..8bf705b1ad 100644 --- a/tests/field_deconstruction/tests.py +++ b/tests/field_deconstruction/tests.py @@ -214,6 +214,15 @@ class FieldDeconstructionTests(SimpleTestCase): self.assertEqual(path, "django.db.models.ForeignKey") self.assertEqual(args, []) self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "foobar", "on_delete": models.CASCADE}) + # Test limit_choices_to + field = models.ForeignKey("auth.Permission", models.CASCADE, limit_choices_to={'foo': 'bar'}) + name, path, args, kwargs = field.deconstruct() + self.assertEqual(path, "django.db.models.ForeignKey") + self.assertEqual(args, []) + self.assertEqual( + kwargs, + {"to": "auth.Permission", "limit_choices_to": {'foo': 'bar'}, "on_delete": models.CASCADE} + ) @override_settings(AUTH_USER_MODEL="auth.Permission") def test_foreign_key_swapped(self): @@ -228,6 +237,17 @@ class FieldDeconstructionTests(SimpleTestCase): self.assertEqual(kwargs, {"to": "auth.Permission", "on_delete": models.CASCADE}) self.assertEqual(kwargs['to'].setting_name, "AUTH_USER_MODEL") + def test_one_to_one(self): + # Test limit_choices_to + field = models.OneToOneField("auth.Permission", models.CASCADE, limit_choices_to={'foo': 'bar'}) + name, path, args, kwargs = field.deconstruct() + self.assertEqual(path, "django.db.models.OneToOneField") + self.assertEqual(args, []) + self.assertEqual( + kwargs, + {"to": "auth.Permission", "limit_choices_to": {'foo': 'bar'}, "on_delete": models.CASCADE} + ) + def test_image_field(self): field = models.ImageField(upload_to="foo/barness", width_field="width", height_field="height") name, path, args, kwargs = field.deconstruct() @@ -294,6 +314,12 @@ class FieldDeconstructionTests(SimpleTestCase): self.assertEqual(path, "django.db.models.ManyToManyField") self.assertEqual(args, []) self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "custom_table"}) + # Test limit_choices_to + field = models.ManyToManyField("auth.Permission", limit_choices_to={'foo': 'bar'}) + name, path, args, kwargs = field.deconstruct() + self.assertEqual(path, "django.db.models.ManyToManyField") + self.assertEqual(args, []) + self.assertEqual(kwargs, {"to": "auth.Permission", "limit_choices_to": {'foo': 'bar'}}) @override_settings(AUTH_USER_MODEL="auth.Permission") def test_many_to_many_field_swapped(self):