mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
allow_empty -> pending deprecation in preference of overridden get_queryset.
This commit is contained in:
parent
b70c9cc107
commit
d71a5533f9
|
@ -75,10 +75,9 @@ The following attibutes are used to control pagination when used with list views
|
||||||
* `pagination_serializer_class` - The pagination serializer class to use when determining the style of paginated responses. Defaults to the same value as the `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting.
|
* `pagination_serializer_class` - The pagination serializer class to use when determining the style of paginated responses. Defaults to the same value as the `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting.
|
||||||
* `page_kwarg` - The name of a URL kwarg or URL query parameter which can be used by the client to control which page is requested. Defaults to `'page'`.
|
* `page_kwarg` - The name of a URL kwarg or URL query parameter which can be used by the client to control which page is requested. Defaults to `'page'`.
|
||||||
|
|
||||||
**Other**:
|
**Filtering**:
|
||||||
|
|
||||||
* `filter_backend` - The filter backend class that should be used for filtering the queryset. Defaults to the same value as the `FILTER_BACKEND` setting.
|
* `filter_backend` - The filter backend class that should be used for filtering the queryset. Defaults to the same value as the `FILTER_BACKEND` setting.
|
||||||
* `allow_empty` - Determines if an empty list should successfully display zero results, or return a 404 response. Defaults to `True`, meaning empty lists will return sucessful `200 OK` responses, with zero results.
|
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
|
|
|
@ -152,9 +152,21 @@ And would have the following entry in the urlconf:
|
||||||
|
|
||||||
url(r'^users/(?P<username>\w+)/$', UserDetail.as_view()),
|
url(r'^users/(?P<username>\w+)/$', UserDetail.as_view()),
|
||||||
|
|
||||||
|
|
||||||
Usage of the old-style attributes continues to be supported, but will raise a `PendingDeprecationWarning`.
|
Usage of the old-style attributes continues to be supported, but will raise a `PendingDeprecationWarning`.
|
||||||
|
|
||||||
|
The `allow_empty` attribute is also deprecated. To use `allow_empty=False` style behavior you should explicitly override `get_queryset` and raise an `Http404` on empty querysets.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
class DisallowEmptyQuerysetMixin(object):
|
||||||
|
def get_queryset(self):
|
||||||
|
queryset = super(DisallowEmptyQuerysetMixin, self).get_queryset()
|
||||||
|
if not queryset.exists():
|
||||||
|
raise Http404
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
In our opinion removing lesser-used attributes like `allow_empty` helps us move towards simpler generic view implementations, making them more obvious to use and override, and re-inforcing the preferred style of developers writing their own base classes and mixins for custom behavior rather than relying on the configurability of the generic views.
|
||||||
|
|
||||||
## Simpler URL lookups
|
## Simpler URL lookups
|
||||||
|
|
||||||
The `HyperlinkedRelatedField` class now takes a single optional `lookup_field` argument, that replaces the `pk_url_kwarg`, `slug_url_kwarg`, and `slug_field` arguments.
|
The `HyperlinkedRelatedField` class now takes a single optional `lookup_field` argument, that replaces the `pk_url_kwarg`, `slug_url_kwarg`, and `slug_field` arguments.
|
||||||
|
|
|
@ -3,7 +3,10 @@ Provides generic filtering backends that can be used to filter the results
|
||||||
returned by list views.
|
returned by list views.
|
||||||
"""
|
"""
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
from rest_framework.compat import django_filters
|
from rest_framework.compat import django_filters
|
||||||
|
import operator
|
||||||
|
|
||||||
FilterSet = django_filters and django_filters.FilterSet or None
|
FilterSet = django_filters and django_filters.FilterSet or None
|
||||||
|
|
||||||
|
@ -62,3 +65,29 @@ class DjangoFilterBackend(BaseFilterBackend):
|
||||||
return filter_class(request.QUERY_PARAMS, queryset=queryset).qs
|
return filter_class(request.QUERY_PARAMS, queryset=queryset).qs
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
class SearchFilter(BaseFilterBackend):
|
||||||
|
def construct_search(self, field_name):
|
||||||
|
if field_name.startswith('^'):
|
||||||
|
return "%s__istartswith" % field_name[1:]
|
||||||
|
elif field_name.startswith('='):
|
||||||
|
return "%s__iexact" % field_name[1:]
|
||||||
|
elif field_name.startswith('@'):
|
||||||
|
return "%s__search" % field_name[1:]
|
||||||
|
else:
|
||||||
|
return "%s__icontains" % field_name
|
||||||
|
|
||||||
|
def filter_queryset(self, request, queryset, view):
|
||||||
|
search_fields = getattr(view, 'search_fields', None)
|
||||||
|
|
||||||
|
if not search_fields:
|
||||||
|
return None
|
||||||
|
|
||||||
|
orm_lookups = [self.construct_search(str(search_field))
|
||||||
|
for search_field in self.search_fields]
|
||||||
|
for bit in self.query.split():
|
||||||
|
or_queries = [models.Q(**{orm_lookup: bit})
|
||||||
|
for orm_lookup in orm_lookups]
|
||||||
|
queryset = queryset.filter(reduce(operator.or_, or_queries))
|
||||||
|
return queryset
|
||||||
|
|
|
@ -42,9 +42,6 @@ class GenericAPIView(views.APIView):
|
||||||
# The filter backend class to use for queryset filtering
|
# The filter backend class to use for queryset filtering
|
||||||
filter_backend = api_settings.FILTER_BACKEND
|
filter_backend = api_settings.FILTER_BACKEND
|
||||||
|
|
||||||
# Determines if the view will return 200 or 404 responses for empty lists.
|
|
||||||
allow_empty = True
|
|
||||||
|
|
||||||
# The following attributes may be subject to change,
|
# The following attributes may be subject to change,
|
||||||
# and should be considered private API.
|
# and should be considered private API.
|
||||||
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
||||||
|
@ -56,6 +53,7 @@ class GenericAPIView(views.APIView):
|
||||||
pk_url_kwarg = 'pk'
|
pk_url_kwarg = 'pk'
|
||||||
slug_url_kwarg = 'slug'
|
slug_url_kwarg = 'slug'
|
||||||
slug_field = 'slug'
|
slug_field = 'slug'
|
||||||
|
allow_empty = True
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
"""
|
"""
|
||||||
|
@ -111,6 +109,14 @@ class GenericAPIView(views.APIView):
|
||||||
if not page_size:
|
if not page_size:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not self.allow_empty:
|
||||||
|
warnings.warn(
|
||||||
|
'The `allow_empty` parameter is due to be deprecated. '
|
||||||
|
'To use `allow_empty=False` style behavior, You should override '
|
||||||
|
'`get_queryset()` and explicitly raise a 404 on empty querysets.',
|
||||||
|
PendingDeprecationWarning, stacklevel=2
|
||||||
|
)
|
||||||
|
|
||||||
paginator = self.paginator_class(queryset, page_size,
|
paginator = self.paginator_class(queryset, page_size,
|
||||||
allow_empty_first_page=self.allow_empty)
|
allow_empty_first_page=self.allow_empty)
|
||||||
page_kwarg = self.kwargs.get(self.page_kwarg)
|
page_kwarg = self.kwargs.get(self.page_kwarg)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user