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):