Skip to content

Commit 592eea9

Browse files
kmwenjatomchristie
authored andcommitted
* Use get_serializer_class in ordering filter* Test improper configuration of ordering* Raise ImproperlyConfigured when missing get_serializer_class
* Use get_serializer_class in ordering filter * Test improper configuration of ordering * Raise ImproperlyConfigured when missing get_serializer_class
1 parent 2d20f09 commit 592eea9

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

rest_framework/filters.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,14 @@ def get_valid_fields(self, queryset, view):
227227

228228
if valid_fields is None:
229229
# Default to allowing filtering on serializer fields
230-
serializer_class = getattr(view, 'serializer_class')
231-
if serializer_class is None:
230+
try:
231+
serializer_class = view.get_serializer_class()
232+
except AssertionError: # raised if no serializer_class was found
232233
msg = ("Cannot use %s on a view which does not have either a "
233-
"'serializer_class' or 'ordering_fields' attribute.")
234+
"'serializer_class', an overriding 'get_serializer_class' "
235+
"or 'ordering_fields' attribute.")
234236
raise ImproperlyConfigured(msg % self.__class__.__name__)
237+
235238
valid_fields = [
236239
(field.source or field_name, field.label)
237240
for field_name, field in serializer_class().fields.items()

tests/test_filters.py

+36
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from decimal import Decimal
66

77
from django.conf.urls import url
8+
from django.core.exceptions import ImproperlyConfigured
89
from django.core.urlresolvers import reverse
910
from django.db import models
1011
from django.test import TestCase
@@ -754,6 +755,41 @@ class OrderingListView(generics.ListAPIView):
754755

755756
self.assertContains(response, 'verbose title')
756757

758+
def test_ordering_with_overridden_get_serializer_class(self):
759+
class OrderingListView(generics.ListAPIView):
760+
queryset = OrderingFilterModel.objects.all()
761+
filter_backends = (filters.OrderingFilter,)
762+
ordering = ('title',)
763+
# note: no ordering_fields and serializer_class speficied
764+
765+
def get_serializer_class(self):
766+
return OrderingFilterSerializer
767+
768+
view = OrderingListView.as_view()
769+
request = factory.get('/', {'ordering': 'text'})
770+
response = view(request)
771+
self.assertEqual(
772+
response.data,
773+
[
774+
{'id': 1, 'title': 'zyx', 'text': 'abc'},
775+
{'id': 2, 'title': 'yxw', 'text': 'bcd'},
776+
{'id': 3, 'title': 'xwv', 'text': 'cde'},
777+
]
778+
)
779+
780+
def test_ordering_with_improper_configuration(self):
781+
class OrderingListView(generics.ListAPIView):
782+
queryset = OrderingFilterModel.objects.all()
783+
filter_backends = (filters.OrderingFilter,)
784+
ordering = ('title',)
785+
# note: no ordering_fields and serializer_class
786+
# or get_serializer_class speficied
787+
788+
view = OrderingListView.as_view()
789+
request = factory.get('/', {'ordering': 'text'})
790+
with self.assertRaises(ImproperlyConfigured):
791+
view(request)
792+
757793

758794
class SensitiveOrderingFilterModel(models.Model):
759795
username = models.CharField(max_length=20)

0 commit comments

Comments
 (0)