Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: encode/django-rest-framework
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: koordinates/django-rest-framework
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: kx-3.12.x
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 2 commits
  • 5 files changed
  • 1 contributor

Commits on Jul 15, 2021

  1. Copy the full SHA
    036f925 View commit details
  2. Copy the full SHA
    f9325aa View commit details
Showing with 52 additions and 43 deletions.
  1. +7 −6 rest_framework/fields.py
  2. +1 −31 rest_framework/generics.py
  3. +35 −0 rest_framework/mixins.py
  4. +6 −4 rest_framework/relations.py
  5. +3 −2 tests/test_fields.py
13 changes: 7 additions & 6 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
@@ -375,12 +375,13 @@ def bind(self, field_name, parent):
# In order to enforce a consistent style, we error if a redundant
# 'source' argument has been used. For example:
# my_field = serializer.CharField(source='my_field')
assert self.source != field_name, (
"It is redundant to specify `source='%s'` on field '%s' in "
"serializer '%s', because it is the same as the field name. "
"Remove the `source` keyword argument." %
(field_name, self.__class__.__name__, parent.__class__.__name__)
)
if field_name == self.source:
warnings.warn(
"It is redundant to specify `source='%s'` on field '%s' in "
"serializer '%s', because it is the same as the field name. "
"Remove the `source` keyword argument." %
(field_name, self.__class__.__name__, parent.__class__.__name__),
)

self.field_name = field_name
self.parent = parent
32 changes: 1 addition & 31 deletions rest_framework/generics.py
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ def get_object_or_404(queryset, *filter_args, **filter_kwargs):
raise Http404


class GenericAPIView(views.APIView):
class GenericAPIView(mixins.PaginationMixin, views.APIView):
"""
Base class for all other generic views.
"""
@@ -42,9 +42,6 @@ class GenericAPIView(views.APIView):
# The filter backend classes to use for queryset filtering
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS

# The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

def get_queryset(self):
"""
Get the list of items for this view.
@@ -150,33 +147,6 @@ def filter_queryset(self, queryset):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset

@property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator

def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)

def get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data)


# Concrete view classes that provide method handlers
# by composing the mixin classes with the base view.
35 changes: 35 additions & 0 deletions rest_framework/mixins.py
Original file line number Diff line number Diff line change
@@ -30,6 +30,41 @@ def get_success_headers(self, data):
return {}


class PaginationMixin(object):
"""
Adds pagination methods to a view.
"""
# The style to use for queryset pagination.
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS

@property
def paginator(self):
"""
The paginator instance associated with the view, or `None`.
"""
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator

def get_paginated_response(self, data):
"""
Return a paginated style `Response` object for the given output data.
"""
assert self.paginator is not None
return self.paginator.get_paginated_response(data)

def paginate_queryset(self, queryset):
"""
Return a single page of results, or `None` if pagination is disabled.
"""
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)


class ListModelMixin:
"""
List a queryset.
10 changes: 6 additions & 4 deletions rest_framework/relations.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys
import warnings
from collections import OrderedDict
from urllib import parse

@@ -108,10 +109,11 @@ def __init__(self, **kwargs):
'Relational field must provide a `queryset` argument, '
'override `get_queryset`, or set read_only=`True`.'
)
assert not (self.queryset is not None and kwargs.get('read_only')), (
'Relational fields should not provide a `queryset` argument, '
'when setting read_only=`True`.'
)
if self.queryset is not None and kwargs.get('read_only'):
warnings.warn(
'Relational fields should not provide a `queryset` argument, '
'when setting read_only=`True`.'
)
kwargs.pop('many', None)
kwargs.pop('allow_empty', None)
super().__init__(**kwargs)
5 changes: 3 additions & 2 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
@@ -186,9 +186,10 @@ class ExampleSerializer(serializers.Serializer):
def test_redundant_source(self):
class ExampleSerializer(serializers.Serializer):
example_field = serializers.CharField(source='example_field')
with pytest.raises(AssertionError) as exc_info:
with pytest.warns(UserWarning) as record:
ExampleSerializer().fields
assert str(exc_info.value) == (
assert len(record) == 1
assert record[0].message.args[0] == (
"It is redundant to specify `source='example_field'` on field "
"'CharField' in serializer 'ExampleSerializer', because it is the "
"same as the field name. Remove the `source` keyword argument."