Skip to content

Commit

Permalink
Fix #1811: take limit_choices_to into account with FK (#6371)
Browse files Browse the repository at this point in the history
* Fix issue1811: take limit_choices_to into account with FK

* Issue 1811: Add tests to illustrate issue

* Filter queryset only if limit_choices_to exists

* Move test_relations_with_limited_querysets file within test_relations_pk

* move limit_choices_to logic from relations.py to utils/field_mapping.py

* move limit_choices_to above other check to avoid conflicts
  • Loading branch information
adrienbrunet authored and tomchristie committed Jan 8, 2019
1 parent 9c408b2 commit e3bd4b9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
4 changes: 4 additions & 0 deletions rest_framework/utils/field_mapping.py
Expand Up @@ -249,6 +249,10 @@ def get_relation_kwargs(field_name, relation_info):
if to_field:
kwargs['to_field'] = to_field

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 has_through_model:
kwargs['read_only'] = True
kwargs.pop('queryset', None)
Expand Down
7 changes: 7 additions & 0 deletions tests/models.py
Expand Up @@ -52,6 +52,13 @@ class ForeignKeySource(RESTFrameworkModel):
on_delete=models.CASCADE)


class ForeignKeySourceWithLimitedChoices(RESTFrameworkModel):
target = models.ForeignKey(ForeignKeyTarget, help_text='Target',
verbose_name='Target',
limit_choices_to={"name__startswith": "limited-"},
on_delete=models.CASCADE)


# Nullable ForeignKey
class NullableForeignKeySource(RESTFrameworkModel):
name = models.CharField(max_length=100)
Expand Down
26 changes: 22 additions & 4 deletions tests/test_relations_pk.py
Expand Up @@ -5,10 +5,10 @@

from rest_framework import serializers
from tests.models import (
ForeignKeySource, ForeignKeyTarget, ManyToManySource, ManyToManyTarget,
NullableForeignKeySource, NullableOneToOneSource,
NullableUUIDForeignKeySource, OneToOnePKSource, OneToOneTarget,
UUIDForeignKeyTarget
ForeignKeySource, ForeignKeySourceWithLimitedChoices, ForeignKeyTarget,
ManyToManySource, ManyToManyTarget, NullableForeignKeySource,
NullableOneToOneSource, NullableUUIDForeignKeySource, OneToOnePKSource,
OneToOneTarget, UUIDForeignKeyTarget
)


Expand Down Expand Up @@ -38,6 +38,12 @@ class Meta:
fields = ('id', 'name', 'target')


class ForeignKeySourceWithLimitedChoicesSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeySourceWithLimitedChoices
fields = ("id", "target")


# Nullable ForeignKey
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
Expand Down Expand Up @@ -360,6 +366,18 @@ class Meta(ForeignKeySourceSerializer.Meta):
serializer.is_valid(raise_exception=True)
assert 'target' not in serializer.validated_data

def test_queryset_size_without_limited_choices(self):
limited_target = ForeignKeyTarget(name="limited-target")
limited_target.save()
queryset = ForeignKeySourceSerializer().fields["target"].get_queryset()
assert len(queryset) == 3

def test_queryset_size_with_limited_choices(self):
limited_target = ForeignKeyTarget(name="limited-target")
limited_target.save()
queryset = ForeignKeySourceWithLimitedChoicesSerializer().fields["target"].get_queryset()
assert len(queryset) == 1


class PKNullableForeignKeyTests(TestCase):
def setUp(self):
Expand Down

0 comments on commit e3bd4b9

Please sign in to comment.