mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-23 01:57:00 +03:00
Merge pull request #844 from rouge8/hyperlinkedidentityfield-lookup_field
HyperlinkedIdentityField uses `lookup_field` kwarg.
This commit is contained in:
commit
4ade7fb82c
|
@ -196,15 +196,13 @@ Would serialize to a representation like this:
|
|||
'artist': 'Thom Yorke'
|
||||
'track_listing': 'http://www.example.com/api/track_list/12/',
|
||||
}
|
||||
|
||||
|
||||
This field is always read-only.
|
||||
|
||||
**Arguments**:
|
||||
|
||||
* `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'`.
|
||||
* `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`.
|
||||
* `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'`.
|
||||
* `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.
|
||||
"""
|
||||
lookup_field = 'pk'
|
||||
read_only = True
|
||||
|
||||
# These are all pending deprecation
|
||||
pk_url_kwarg = 'pk'
|
||||
slug_field = 'slug'
|
||||
slug_url_kwarg = None # Defaults to same as `slug_field` unless overridden
|
||||
read_only = True
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
# 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
|
||||
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)
|
||||
default_slug_kwarg = self.slug_url_kwarg or self.slug_field
|
||||
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)
|
||||
format = self.context.get('format', None)
|
||||
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:
|
||||
warnings.warn("Using `HyperlinkedIdentityField` without including the "
|
||||
|
|
|
@ -27,6 +27,14 @@ class PhotoSerializer(serializers.Serializer):
|
|||
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):
|
||||
model = BasicModel
|
||||
model_serializer_class = serializers.HyperlinkedModelSerializer
|
||||
|
@ -73,6 +81,8 @@ class PhotoListCreate(generics.ListCreateAPIView):
|
|||
|
||||
class AlbumDetail(generics.RetrieveAPIView):
|
||||
model = Album
|
||||
serializer_class = AlbumSerializer
|
||||
lookup_field = 'title'
|
||||
|
||||
|
||||
class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
|
@ -180,6 +190,36 @@ class TestManyToManyHyperlinkedView(TestCase):
|
|||
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):
|
||||
urls = 'rest_framework.tests.hyperlinkedserializers'
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user