Skip to content

Commit

Permalink
Fix dotted source ordering (encode#5533)
Browse files Browse the repository at this point in the history
* replaced '.' for '__' in dotted ordering sources

* Add test for non-dotted source.
  • Loading branch information
carltongibson authored Oct 25, 2017
1 parent 7261ae6 commit 1f693c3
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
2 changes: 1 addition & 1 deletion rest_framework/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def get_default_valid_fields(self, queryset, view, context={}):
raise ImproperlyConfigured(msg % self.__class__.__name__)

return [
(field.source or field_name, field.label)
(field.source.replace('.', '__') or field_name, field.label)
for field_name, field in serializer_class(context=context).fields.items()
if not getattr(field, 'write_only', False) and not field.source == '*'
]
Expand Down
44 changes: 44 additions & 0 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ class OrderingFilterModel(models.Model):

class OrderingFilterRelatedModel(models.Model):
related_object = models.ForeignKey(OrderingFilterModel, related_name="relateds", on_delete=models.CASCADE)
index = models.SmallIntegerField(help_text="A non-related field to test with", default=0)


class OrderingFilterSerializer(serializers.ModelSerializer):
Expand All @@ -320,6 +321,19 @@ class Meta:
fields = '__all__'


class OrderingDottedRelatedSerializer(serializers.ModelSerializer):
related_text = serializers.CharField(source='related_object.text')
related_title = serializers.CharField(source='related_object.title')

class Meta:
model = OrderingFilterRelatedModel
fields = (
'related_text',
'related_title',
'index',
)


class DjangoFilterOrderingModel(models.Model):
date = models.DateField()
text = models.CharField(max_length=10)
Expand Down Expand Up @@ -484,6 +498,36 @@ class OrderingListView(generics.ListAPIView):
{'id': 2, 'title': 'yxw', 'text': 'bcd'},
]

def test_ordering_by_dotted_source(self):

for index, obj in enumerate(OrderingFilterModel.objects.all()):
OrderingFilterRelatedModel.objects.create(
related_object=obj,
index=index
)

class OrderingListView(generics.ListAPIView):
serializer_class = OrderingDottedRelatedSerializer
filter_backends = (filters.OrderingFilter,)
queryset = OrderingFilterRelatedModel.objects.all()

view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'related_object__text'})
response = view(request)
assert response.data == [
{'related_title': 'zyx', 'related_text': 'abc', 'index': 0},
{'related_title': 'yxw', 'related_text': 'bcd', 'index': 1},
{'related_title': 'xwv', 'related_text': 'cde', 'index': 2},
]

request = factory.get('/', {'ordering': '-index'})
response = view(request)
assert response.data == [
{'related_title': 'xwv', 'related_text': 'cde', 'index': 2},
{'related_title': 'yxw', 'related_text': 'bcd', 'index': 1},
{'related_title': 'zyx', 'related_text': 'abc', 'index': 0},
]

def test_ordering_with_nonstandard_ordering_param(self):
with override_settings(REST_FRAMEWORK={'ORDERING_PARAM': 'order'}):
reload_module(filters)
Expand Down

0 comments on commit 1f693c3

Please sign in to comment.