mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-29 21:14:01 +03:00
HyperlinkedIdentityField uses lookup_field
kwarg.
According to the [Serializers API Guide][1], `HyperlinkedIdentityField` takes `lookup_field` as a kwarg like the other related fields and the generic views. However, this was not actually implemented. [1]: http://django-rest-framework.org/api-guide/serializers.html#hyperlinkedmodelserializer
This commit is contained in:
parent
0e81ffced2
commit
abe207b869
|
@ -202,9 +202,7 @@ This field is always read-only.
|
||||||
**Arguments**:
|
**Arguments**:
|
||||||
|
|
||||||
* `view_name` - The view name that should be used as the target of the relationship. **required**.
|
* `view_name` - The view name that should be used as the target of the relationship. **required**.
|
||||||
* `slug_field` - The field on the target that should be used for the lookup. Default is `'slug'`.
|
* `lookup_field` - The field on the target that should be used for the lookup. Should correspond to a URL keyword argument on the referenced view. Default is `'pk'`.
|
||||||
* `pk_url_kwarg` - The named url parameter for the pk field lookup. Default is `pk`.
|
|
||||||
* `slug_url_kwarg` - The named url parameter for the slug field lookup. Default is to use the same value as given for `slug_field`.
|
|
||||||
* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument.
|
* `format` - If using format suffixes, hyperlinked fields will use the same format suffix for the target unless overridden by using the `format` argument.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -465,10 +465,13 @@ class HyperlinkedIdentityField(Field):
|
||||||
"""
|
"""
|
||||||
Represents the instance, or a property on the instance, using hyperlinking.
|
Represents the instance, or a property on the instance, using hyperlinking.
|
||||||
"""
|
"""
|
||||||
|
lookup_field = 'pk'
|
||||||
|
read_only = True
|
||||||
|
|
||||||
|
# These are all pending deprecation
|
||||||
pk_url_kwarg = 'pk'
|
pk_url_kwarg = 'pk'
|
||||||
slug_field = 'slug'
|
slug_field = 'slug'
|
||||||
slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
|
slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
|
||||||
read_only = True
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# TODO: Make view_name mandatory, and have the
|
# TODO: Make view_name mandatory, and have the
|
||||||
|
@ -477,6 +480,19 @@ class HyperlinkedIdentityField(Field):
|
||||||
# Optionally the format of the target hyperlink may be specified
|
# Optionally the format of the target hyperlink may be specified
|
||||||
self.format = kwargs.pop('format', None)
|
self.format = kwargs.pop('format', None)
|
||||||
|
|
||||||
|
self.lookup_field = kwargs.pop('lookup_field', self.lookup_field)
|
||||||
|
|
||||||
|
# These are pending deprecation
|
||||||
|
if 'pk_url_kwarg' in kwargs:
|
||||||
|
msg = 'pk_url_kwarg is pending deprecation. Use lookup_field instead.'
|
||||||
|
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
|
||||||
|
if 'slug_url_kwarg' in kwargs:
|
||||||
|
msg = 'slug_url_kwarg is pending deprecation. Use lookup_field instead.'
|
||||||
|
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
|
||||||
|
if 'slug_field' in kwargs:
|
||||||
|
msg = 'slug_field is pending deprecation. Use lookup_field instead.'
|
||||||
|
warnings.warn(msg, PendingDeprecationWarning, stacklevel=2)
|
||||||
|
|
||||||
self.slug_field = kwargs.pop('slug_field', self.slug_field)
|
self.slug_field = kwargs.pop('slug_field', self.slug_field)
|
||||||
default_slug_kwarg = self.slug_url_kwarg or 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.pk_url_kwarg = kwargs.pop('pk_url_kwarg', self.pk_url_kwarg)
|
||||||
|
@ -488,7 +504,8 @@ class HyperlinkedIdentityField(Field):
|
||||||
request = self.context.get('request', None)
|
request = self.context.get('request', None)
|
||||||
format = self.context.get('format', None)
|
format = self.context.get('format', None)
|
||||||
view_name = self.view_name or self.parent.opts.view_name
|
view_name = self.view_name or self.parent.opts.view_name
|
||||||
kwargs = {self.pk_url_kwarg: obj.pk}
|
lookup_field = getattr(obj, self.lookup_field)
|
||||||
|
kwargs = {self.lookup_field: lookup_field}
|
||||||
|
|
||||||
if request is None:
|
if request is None:
|
||||||
warnings.warn("Using `HyperlinkedIdentityField` without including the "
|
warnings.warn("Using `HyperlinkedIdentityField` without including the "
|
||||||
|
|
|
@ -27,6 +27,14 @@ class PhotoSerializer(serializers.Serializer):
|
||||||
return Photo(**attrs)
|
return Photo(**attrs)
|
||||||
|
|
||||||
|
|
||||||
|
class AlbumSerializer(serializers.ModelSerializer):
|
||||||
|
url = serializers.HyperlinkedIdentityField(view_name='album-detail', lookup_field='title')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Album
|
||||||
|
fields = ('title', 'url')
|
||||||
|
|
||||||
|
|
||||||
class BasicList(generics.ListCreateAPIView):
|
class BasicList(generics.ListCreateAPIView):
|
||||||
model = BasicModel
|
model = BasicModel
|
||||||
model_serializer_class = serializers.HyperlinkedModelSerializer
|
model_serializer_class = serializers.HyperlinkedModelSerializer
|
||||||
|
@ -73,6 +81,8 @@ class PhotoListCreate(generics.ListCreateAPIView):
|
||||||
|
|
||||||
class AlbumDetail(generics.RetrieveAPIView):
|
class AlbumDetail(generics.RetrieveAPIView):
|
||||||
model = Album
|
model = Album
|
||||||
|
serializer_class = AlbumSerializer
|
||||||
|
lookup_field = 'title'
|
||||||
|
|
||||||
|
|
||||||
class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
|
class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
@ -180,6 +190,36 @@ class TestManyToManyHyperlinkedView(TestCase):
|
||||||
self.assertEqual(response.data, self.data[0])
|
self.assertEqual(response.data, self.data[0])
|
||||||
|
|
||||||
|
|
||||||
|
class TestHyperlinkedIdentityFieldLookup(TestCase):
|
||||||
|
urls = 'rest_framework.tests.hyperlinkedserializers'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create 3 Album instances.
|
||||||
|
"""
|
||||||
|
titles = ['foo', 'bar', 'baz']
|
||||||
|
for title in titles:
|
||||||
|
album = Album(title=title)
|
||||||
|
album.save()
|
||||||
|
self.detail_view = AlbumDetail.as_view()
|
||||||
|
self.data = {
|
||||||
|
'foo': {'title': 'foo', 'url': 'http://testserver/albums/foo/'},
|
||||||
|
'bar': {'title': 'bar', 'url': 'http://testserver/albums/bar/'},
|
||||||
|
'baz': {'title': 'baz', 'url': 'http://testserver/albums/baz/'}
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_lookup_field(self):
|
||||||
|
"""
|
||||||
|
GET requests to AlbumDetail view should return serialized Albums
|
||||||
|
with a url field keyed by `title`.
|
||||||
|
"""
|
||||||
|
for album in Album.objects.all():
|
||||||
|
request = factory.get('/albums/{0}/'.format(album.title))
|
||||||
|
response = self.detail_view(request, title=album.title)
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
self.assertEqual(response.data, self.data[album.title])
|
||||||
|
|
||||||
|
|
||||||
class TestCreateWithForeignKeys(TestCase):
|
class TestCreateWithForeignKeys(TestCase):
|
||||||
urls = 'rest_framework.tests.hyperlinkedserializers'
|
urls = 'rest_framework.tests.hyperlinkedserializers'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user