diff --git a/rest_framework/utils/field_mapping.py b/rest_framework/utils/field_mapping.py index 991f20f17a6..f11b4b94e61 100644 --- a/rest_framework/utils/field_mapping.py +++ b/rest_framework/utils/field_mapping.py @@ -251,7 +251,9 @@ def get_relation_kwargs(field_name, relation_info): limit_choices_to = model_field and model_field.get_limit_choices_to() if limit_choices_to: - kwargs['queryset'] = kwargs['queryset'].filter(**limit_choices_to) + if not isinstance(limit_choices_to, models.Q): + limit_choices_to = models.Q(**limit_choices_to) + kwargs['queryset'] = kwargs['queryset'].filter(limit_choices_to) if has_through_model: kwargs['read_only'] = True diff --git a/tests/models.py b/tests/models.py index 55f250e046b..17bf23cda44 100644 --- a/tests/models.py +++ b/tests/models.py @@ -59,6 +59,13 @@ class ForeignKeySourceWithLimitedChoices(RESTFrameworkModel): on_delete=models.CASCADE) +class ForeignKeySourceWithQLimitedChoices(RESTFrameworkModel): + target = models.ForeignKey(ForeignKeyTarget, help_text='Target', + verbose_name='Target', + limit_choices_to=models.Q(name__startswith="limited-"), + on_delete=models.CASCADE) + + # Nullable ForeignKey class NullableForeignKeySource(RESTFrameworkModel): name = models.CharField(max_length=100) diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py index 31b6bb8677f..2cffb62e6bf 100644 --- a/tests/test_relations_pk.py +++ b/tests/test_relations_pk.py @@ -5,10 +5,11 @@ from rest_framework import serializers from tests.models import ( - ForeignKeySource, ForeignKeySourceWithLimitedChoices, ForeignKeyTarget, - ManyToManySource, ManyToManyTarget, NullableForeignKeySource, - NullableOneToOneSource, NullableUUIDForeignKeySource, OneToOnePKSource, - OneToOneTarget, UUIDForeignKeyTarget + ForeignKeySource, ForeignKeySourceWithLimitedChoices, + ForeignKeySourceWithQLimitedChoices, ForeignKeyTarget, ManyToManySource, + ManyToManyTarget, NullableForeignKeySource, NullableOneToOneSource, + NullableUUIDForeignKeySource, OneToOnePKSource, OneToOneTarget, + UUIDForeignKeyTarget ) @@ -378,6 +379,18 @@ def test_queryset_size_with_limited_choices(self): queryset = ForeignKeySourceWithLimitedChoicesSerializer().fields["target"].get_queryset() assert len(queryset) == 1 + def test_queryset_size_with_Q_limited_choices(self): + limited_target = ForeignKeyTarget(name="limited-target") + limited_target.save() + + class QLimitedChoicesSerializer(serializers.ModelSerializer): + class Meta: + model = ForeignKeySourceWithQLimitedChoices + fields = ("id", "target") + + queryset = QLimitedChoicesSerializer().fields["target"].get_queryset() + assert len(queryset) == 1 + class PKNullableForeignKeyTests(TestCase): def setUp(self):