Skip to content

Commit

Permalink
* Use get_serializer_class in ordering filter* Test improper configur…
Browse files Browse the repository at this point in the history
…ation 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
  • Loading branch information
kmwenja authored and tomchristie committed May 26, 2016
1 parent 2d20f09 commit 592eea9
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
9 changes: 6 additions & 3 deletions rest_framework/filters.py
Expand Up @@ -227,11 +227,14 @@ def get_valid_fields(self, queryset, view):

if valid_fields is None:
# Default to allowing filtering on serializer fields
serializer_class = getattr(view, 'serializer_class')
if serializer_class is None:
try:
serializer_class = view.get_serializer_class()
except AssertionError: # raised if no serializer_class was found
msg = ("Cannot use %s on a view which does not have either a "
"'serializer_class' or 'ordering_fields' attribute.")
"'serializer_class', an overriding 'get_serializer_class' "
"or 'ordering_fields' attribute.")
raise ImproperlyConfigured(msg % self.__class__.__name__)

valid_fields = [
(field.source or field_name, field.label)
for field_name, field in serializer_class().fields.items()
Expand Down
36 changes: 36 additions & 0 deletions tests/test_filters.py
Expand Up @@ -5,6 +5,7 @@
from decimal import Decimal

from django.conf.urls import url
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
from django.db import models
from django.test import TestCase
Expand Down Expand Up @@ -754,6 +755,41 @@ class OrderingListView(generics.ListAPIView):

self.assertContains(response, 'verbose title')

def test_ordering_with_overridden_get_serializer_class(self):
class OrderingListView(generics.ListAPIView):
queryset = OrderingFilterModel.objects.all()
filter_backends = (filters.OrderingFilter,)
ordering = ('title',)
# note: no ordering_fields and serializer_class speficied

def get_serializer_class(self):
return OrderingFilterSerializer

view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'text'})
response = view(request)
self.assertEqual(
response.data,
[
{'id': 1, 'title': 'zyx', 'text': 'abc'},
{'id': 2, 'title': 'yxw', 'text': 'bcd'},
{'id': 3, 'title': 'xwv', 'text': 'cde'},
]
)

def test_ordering_with_improper_configuration(self):
class OrderingListView(generics.ListAPIView):
queryset = OrderingFilterModel.objects.all()
filter_backends = (filters.OrderingFilter,)
ordering = ('title',)
# note: no ordering_fields and serializer_class
# or get_serializer_class speficied

view = OrderingListView.as_view()
request = factory.get('/', {'ordering': 'text'})
with self.assertRaises(ImproperlyConfigured):
view(request)


class SensitiveOrderingFilterModel(models.Model):
username = models.CharField(max_length=20)
Expand Down

0 comments on commit 592eea9

Please sign in to comment.