mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-02 20:54:42 +03:00
parent
b3bbf41670
commit
e5e6329a22
|
@ -76,13 +76,6 @@ class GenericAPIView(views.APIView):
|
||||||
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
model_serializer_class = api_settings.DEFAULT_MODEL_SERIALIZER_CLASS
|
||||||
paginator_class = Paginator
|
paginator_class = Paginator
|
||||||
|
|
||||||
######################################
|
|
||||||
# These are pending deprecation...
|
|
||||||
|
|
||||||
pk_url_kwarg = 'pk'
|
|
||||||
slug_url_kwarg = 'slug'
|
|
||||||
slug_field = 'slug'
|
|
||||||
|
|
||||||
def get_serializer_context(self):
|
def get_serializer_context(self):
|
||||||
"""
|
"""
|
||||||
Extra context provided to the serializer class.
|
Extra context provided to the serializer class.
|
||||||
|
@ -270,7 +263,7 @@ class GenericAPIView(views.APIView):
|
||||||
error_format = "'%s' must define 'queryset' or 'model'"
|
error_format = "'%s' must define 'queryset' or 'model'"
|
||||||
raise ImproperlyConfigured(error_format % self.__class__.__name__)
|
raise ImproperlyConfigured(error_format % self.__class__.__name__)
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self):
|
||||||
"""
|
"""
|
||||||
Returns the object the view is displaying.
|
Returns the object the view is displaying.
|
||||||
|
|
||||||
|
@ -278,36 +271,14 @@ class GenericAPIView(views.APIView):
|
||||||
queryset lookups. Eg if objects are referenced using multiple
|
queryset lookups. Eg if objects are referenced using multiple
|
||||||
keyword arguments in the url conf.
|
keyword arguments in the url conf.
|
||||||
"""
|
"""
|
||||||
# Determine the base queryset to use.
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
if queryset is None:
|
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
|
||||||
else:
|
|
||||||
pass # Deprecation warning
|
|
||||||
|
|
||||||
# Perform the lookup filtering.
|
# Perform the lookup filtering.
|
||||||
# Note that `pk` and `slug` are deprecated styles of lookup filtering.
|
# Note that `pk` and `slug` are deprecated styles of lookup filtering.
|
||||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||||
lookup = self.kwargs.get(lookup_url_kwarg, None)
|
lookup = self.kwargs.get(lookup_url_kwarg, None)
|
||||||
pk = self.kwargs.get(self.pk_url_kwarg, None)
|
|
||||||
slug = self.kwargs.get(self.slug_url_kwarg, None)
|
|
||||||
|
|
||||||
if lookup is not None:
|
if lookup is None:
|
||||||
filter_kwargs = {self.lookup_field: lookup}
|
|
||||||
elif pk is not None and self.lookup_field == 'pk':
|
|
||||||
warnings.warn(
|
|
||||||
'The `pk_url_kwarg` attribute is deprecated. '
|
|
||||||
'Use the `lookup_field` attribute instead',
|
|
||||||
DeprecationWarning
|
|
||||||
)
|
|
||||||
filter_kwargs = {'pk': pk}
|
|
||||||
elif slug is not None and self.lookup_field == 'pk':
|
|
||||||
warnings.warn(
|
|
||||||
'The `slug_url_kwarg` attribute is deprecated. '
|
|
||||||
'Use the `lookup_field` attribute instead',
|
|
||||||
DeprecationWarning
|
|
||||||
)
|
|
||||||
filter_kwargs = {self.slug_field: slug}
|
|
||||||
else:
|
|
||||||
raise ImproperlyConfigured(
|
raise ImproperlyConfigured(
|
||||||
'Expected view %s to be called with a URL keyword argument '
|
'Expected view %s to be called with a URL keyword argument '
|
||||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||||
|
@ -315,6 +286,7 @@ class GenericAPIView(views.APIView):
|
||||||
(self.__class__.__name__, self.lookup_field)
|
(self.__class__.__name__, self.lookup_field)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
filter_kwargs = {self.lookup_field: lookup}
|
||||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||||
|
|
||||||
# May raise a permission denied
|
# May raise a permission denied
|
||||||
|
|
|
@ -12,10 +12,9 @@ from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.request import clone_request
|
from rest_framework.request import clone_request
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
|
||||||
def _get_validation_exclusions(obj, pk=None, slug_field=None, lookup_field=None):
|
def _get_validation_exclusions(obj, lookup_field=None):
|
||||||
"""
|
"""
|
||||||
Given a model instance, and an optional pk and slug field,
|
Given a model instance, and an optional pk and slug field,
|
||||||
return the full list of all other field names on that model.
|
return the full list of all other field names on that model.
|
||||||
|
@ -23,23 +22,13 @@ def _get_validation_exclusions(obj, pk=None, slug_field=None, lookup_field=None)
|
||||||
For use when performing full_clean on a model instance,
|
For use when performing full_clean on a model instance,
|
||||||
so we only clean the required fields.
|
so we only clean the required fields.
|
||||||
"""
|
"""
|
||||||
include = []
|
if lookup_field == 'pk':
|
||||||
|
|
||||||
if pk:
|
|
||||||
# Deprecated
|
|
||||||
pk_field = obj._meta.pk
|
pk_field = obj._meta.pk
|
||||||
while pk_field.rel:
|
while pk_field.rel:
|
||||||
pk_field = pk_field.rel.to._meta.pk
|
pk_field = pk_field.rel.to._meta.pk
|
||||||
include.append(pk_field.name)
|
lookup_field = pk_field.name
|
||||||
|
|
||||||
if slug_field:
|
return [field.name for field in obj._meta.fields if field.name != lookup_field]
|
||||||
# Deprecated
|
|
||||||
include.append(slug_field)
|
|
||||||
|
|
||||||
if lookup_field and lookup_field != 'pk':
|
|
||||||
include.append(lookup_field)
|
|
||||||
|
|
||||||
return [field.name for field in obj._meta.fields if field.name not in include]
|
|
||||||
|
|
||||||
|
|
||||||
class CreateModelMixin(object):
|
class CreateModelMixin(object):
|
||||||
|
@ -146,26 +135,15 @@ class UpdateModelMixin(object):
|
||||||
"""
|
"""
|
||||||
Set any attributes on the object that are implicit in the request.
|
Set any attributes on the object that are implicit in the request.
|
||||||
"""
|
"""
|
||||||
# pk and/or slug attributes are implicit in the URL.
|
|
||||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||||
lookup = self.kwargs.get(lookup_url_kwarg, None)
|
lookup_value = self.kwargs[lookup_url_kwarg]
|
||||||
pk = self.kwargs.get(self.pk_url_kwarg, None)
|
|
||||||
slug = self.kwargs.get(self.slug_url_kwarg, None)
|
|
||||||
slug_field = slug and self.slug_field or None
|
|
||||||
|
|
||||||
if lookup:
|
setattr(obj, self.lookup_field, lookup_value)
|
||||||
setattr(obj, self.lookup_field, lookup)
|
|
||||||
|
|
||||||
if pk:
|
|
||||||
setattr(obj, 'pk', pk)
|
|
||||||
|
|
||||||
if slug:
|
|
||||||
setattr(obj, slug_field, slug)
|
|
||||||
|
|
||||||
# Ensure we clean the attributes so that we don't eg return integer
|
# Ensure we clean the attributes so that we don't eg return integer
|
||||||
# pk using a string representation, as provided by the url conf kwarg.
|
# pk using a string representation, as provided by the url conf kwarg.
|
||||||
if hasattr(obj, 'full_clean'):
|
if hasattr(obj, 'full_clean'):
|
||||||
exclude = _get_validation_exclusions(obj, pk, slug_field, self.lookup_field)
|
exclude = _get_validation_exclusions(obj, self.lookup_field)
|
||||||
obj.full_clean(exclude)
|
obj.full_clean(exclude)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ from rest_framework.fields import Field, WritableField, get_component, is_simple
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
from rest_framework.compat import urlparse
|
from rest_framework.compat import urlparse
|
||||||
from rest_framework.compat import smart_text
|
from rest_framework.compat import smart_text
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
|
||||||
# Relational fields
|
# Relational fields
|
||||||
|
@ -320,11 +319,6 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
'incorrect_type': _('Incorrect type. Expected url string, received %s.'),
|
'incorrect_type': _('Incorrect type. Expected url string, received %s.'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# These are all deprecated
|
|
||||||
pk_url_kwarg = 'pk'
|
|
||||||
slug_field = 'slug'
|
|
||||||
slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.view_name = kwargs.pop('view_name')
|
self.view_name = kwargs.pop('view_name')
|
||||||
|
@ -334,22 +328,6 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
self.lookup_field = kwargs.pop('lookup_field', self.lookup_field)
|
self.lookup_field = kwargs.pop('lookup_field', self.lookup_field)
|
||||||
self.format = kwargs.pop('format', None)
|
self.format = kwargs.pop('format', None)
|
||||||
|
|
||||||
# These are deprecated
|
|
||||||
if 'pk_url_kwarg' in kwargs:
|
|
||||||
msg = 'pk_url_kwarg is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
if 'slug_url_kwarg' in kwargs:
|
|
||||||
msg = 'slug_url_kwarg is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
if 'slug_field' in kwargs:
|
|
||||||
msg = 'slug_field is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
self.pk_url_kwarg = kwargs.pop('pk_url_kwarg', self.pk_url_kwarg)
|
|
||||||
self.slug_field = kwargs.pop('slug_field', self.slug_field)
|
|
||||||
default_slug_kwarg = self.slug_url_kwarg or self.slug_field
|
|
||||||
self.slug_url_kwarg = kwargs.pop('slug_url_kwarg', default_slug_kwarg)
|
|
||||||
|
|
||||||
super(HyperlinkedRelatedField, self).__init__(*args, **kwargs)
|
super(HyperlinkedRelatedField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def get_url(self, obj, view_name, request, format):
|
def get_url(self, obj, view_name, request, format):
|
||||||
|
@ -361,39 +339,7 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
"""
|
"""
|
||||||
lookup_field = getattr(obj, self.lookup_field)
|
lookup_field = getattr(obj, self.lookup_field)
|
||||||
kwargs = {self.lookup_field: lookup_field}
|
kwargs = {self.lookup_field: lookup_field}
|
||||||
try:
|
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
||||||
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.pk_url_kwarg != 'pk':
|
|
||||||
# Only try pk if it has been explicitly set.
|
|
||||||
# Otherwise, the default `lookup_field = 'pk'` has us covered.
|
|
||||||
pk = obj.pk
|
|
||||||
kwargs = {self.pk_url_kwarg: pk}
|
|
||||||
try:
|
|
||||||
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
slug = getattr(obj, self.slug_field, None)
|
|
||||||
if slug is not None:
|
|
||||||
# Only try slug if it corresponds to an attribute on the object.
|
|
||||||
kwargs = {self.slug_url_kwarg: slug}
|
|
||||||
try:
|
|
||||||
ret = reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
if self.slug_field == 'slug' and self.slug_url_kwarg == 'slug':
|
|
||||||
# If the lookup succeeds using the default slug params,
|
|
||||||
# then `slug_field` is being used implicitly, and we
|
|
||||||
# we need to warn about the pending deprecation.
|
|
||||||
msg = 'Implicit slug field hyperlinked fields are deprecated.' \
|
|
||||||
'You should set `lookup_field=slug` on the HyperlinkedRelatedField.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
return ret
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
raise NoReverseMatch()
|
|
||||||
|
|
||||||
def get_object(self, queryset, view_name, view_args, view_kwargs):
|
def get_object(self, queryset, view_name, view_args, view_kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -402,19 +348,8 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
Takes the matched URL conf arguments, and the queryset, and should
|
Takes the matched URL conf arguments, and the queryset, and should
|
||||||
return an object instance, or raise an `ObjectDoesNotExist` exception.
|
return an object instance, or raise an `ObjectDoesNotExist` exception.
|
||||||
"""
|
"""
|
||||||
lookup = view_kwargs.get(self.lookup_field, None)
|
lookup_value = view_kwargs[self.lookup_field]
|
||||||
pk = view_kwargs.get(self.pk_url_kwarg, None)
|
filter_kwargs = {self.lookup_field: lookup_value}
|
||||||
slug = view_kwargs.get(self.slug_url_kwarg, None)
|
|
||||||
|
|
||||||
if lookup is not None:
|
|
||||||
filter_kwargs = {self.lookup_field: lookup}
|
|
||||||
elif pk is not None:
|
|
||||||
filter_kwargs = {'pk': pk}
|
|
||||||
elif slug is not None:
|
|
||||||
filter_kwargs = {self.slug_field: slug}
|
|
||||||
else:
|
|
||||||
raise ObjectDoesNotExist()
|
|
||||||
|
|
||||||
return queryset.get(**filter_kwargs)
|
return queryset.get(**filter_kwargs)
|
||||||
|
|
||||||
def to_native(self, obj):
|
def to_native(self, obj):
|
||||||
|
@ -486,11 +421,6 @@ class HyperlinkedIdentityField(Field):
|
||||||
lookup_field = 'pk'
|
lookup_field = 'pk'
|
||||||
read_only = True
|
read_only = True
|
||||||
|
|
||||||
# These are all deprecated
|
|
||||||
pk_url_kwarg = 'pk'
|
|
||||||
slug_field = 'slug'
|
|
||||||
slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.view_name = kwargs.pop('view_name')
|
self.view_name = kwargs.pop('view_name')
|
||||||
|
@ -502,22 +432,6 @@ class HyperlinkedIdentityField(Field):
|
||||||
lookup_field = kwargs.pop('lookup_field', None)
|
lookup_field = kwargs.pop('lookup_field', None)
|
||||||
self.lookup_field = lookup_field or self.lookup_field
|
self.lookup_field = lookup_field or self.lookup_field
|
||||||
|
|
||||||
# These are deprecated
|
|
||||||
if 'pk_url_kwarg' in kwargs:
|
|
||||||
msg = 'pk_url_kwarg is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
if 'slug_url_kwarg' in kwargs:
|
|
||||||
msg = 'slug_url_kwarg is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
if 'slug_field' in kwargs:
|
|
||||||
msg = 'slug_field is deprecated. Use lookup_field instead.'
|
|
||||||
warnings.warn(msg, DeprecationWarning, stacklevel=2)
|
|
||||||
|
|
||||||
self.slug_field = kwargs.pop('slug_field', self.slug_field)
|
|
||||||
default_slug_kwarg = self.slug_url_kwarg or self.slug_field
|
|
||||||
self.pk_url_kwarg = kwargs.pop('pk_url_kwarg', self.pk_url_kwarg)
|
|
||||||
self.slug_url_kwarg = kwargs.pop('slug_url_kwarg', default_slug_kwarg)
|
|
||||||
|
|
||||||
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
|
super(HyperlinkedIdentityField, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def field_to_native(self, obj, field_name):
|
def field_to_native(self, obj, field_name):
|
||||||
|
@ -569,27 +483,4 @@ class HyperlinkedIdentityField(Field):
|
||||||
if lookup_field is None:
|
if lookup_field is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
||||||
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self.pk_url_kwarg != 'pk':
|
|
||||||
# Only try pk lookup if it has been explicitly set.
|
|
||||||
# Otherwise, the default `lookup_field = 'pk'` has us covered.
|
|
||||||
kwargs = {self.pk_url_kwarg: obj.pk}
|
|
||||||
try:
|
|
||||||
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
slug = getattr(obj, self.slug_field, None)
|
|
||||||
if slug:
|
|
||||||
# Only use slug lookup if a slug field exists on the model
|
|
||||||
kwargs = {self.slug_url_kwarg: slug}
|
|
||||||
try:
|
|
||||||
return reverse(view_name, kwargs=kwargs, request=request, format=format)
|
|
||||||
except NoReverseMatch:
|
|
||||||
pass
|
|
||||||
|
|
||||||
raise NoReverseMatch()
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user