From f7497a2c0af901622dddf6ff47fbe73be258ab29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20Gro=C3=9F?= Date: Thu, 13 Dec 2012 12:32:28 +0100 Subject: [PATCH] added tests for url switch in fields --- rest_framework/fields.py | 19 ++++--- rest_framework/reverse.py | 4 +- .../tests/hyperlinkedserializers.py | 54 +++++++++++++++++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 75ce1b9f9..73bd9e2bc 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -543,6 +543,9 @@ class HyperlinkedRelatedField(RelatedField): self.slug_url_kwarg = kwargs.pop('slug_url_kwarg', default_slug_kwarg) self.format = kwargs.pop('format', None) + + self.use_absolute_urls = kwargs.pop('use_absolute_urls', self.parent.use_absolute_urls) + super(HyperlinkedRelatedField, self).__init__(*args, **kwargs) def get_slug_field(self): @@ -555,12 +558,13 @@ class HyperlinkedRelatedField(RelatedField): view_name = self.view_name request = self.context.get('request', None) format = self.format or self.context.get('format', None) + use_absolute_urls = self.use_absolute_urls pk = getattr(obj, 'pk', None) if pk is None: return kwargs = {self.pk_url_kwarg: pk} try: - return reverse(view_name, kwargs=kwargs, request=request, format=format) + return reverse(view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass @@ -571,13 +575,13 @@ class HyperlinkedRelatedField(RelatedField): kwargs = {self.slug_url_kwarg: slug} try: - return reverse(self.view_name, kwargs=kwargs, request=request, format=format) + return reverse(self.view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass kwargs = {self.pk_url_kwarg: obj.pk, self.slug_url_kwarg: slug} try: - return reverse(self.view_name, kwargs=kwargs, request=request, format=format) + return reverse(self.view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass @@ -651,6 +655,8 @@ class HyperlinkedIdentityField(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) + self.use_absolute_urls = kwargs.pop('use_absolute_urls', self.parent.use_absolute_urls) + super(HyperlinkedIdentityField, self).__init__(*args, **kwargs) def field_to_native(self, obj, field_name): @@ -658,8 +664,9 @@ class HyperlinkedIdentityField(Field): format = self.format or self.context.get('format', None) view_name = self.view_name or self.parent.opts.view_name kwargs = {self.pk_url_kwarg: obj.pk} + use_absolute_urls = self.use_absolute_urls try: - return reverse(view_name, kwargs=kwargs, request=request, format=format) + return reverse(view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass @@ -670,13 +677,13 @@ class HyperlinkedIdentityField(Field): kwargs = {self.slug_url_kwarg: slug} try: - return reverse(self.view_name, kwargs=kwargs, request=request, format=format) + return reverse(self.view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass kwargs = {self.pk_url_kwarg: obj.pk, self.slug_url_kwarg: slug} try: - return reverse(self.view_name, kwargs=kwargs, request=request, format=format) + return reverse(self.view_name, kwargs=kwargs, request=request, format=format, use_absolute_urls=use_absolute_urls) except: pass diff --git a/rest_framework/reverse.py b/rest_framework/reverse.py index 4e2c683be..34108fa85 100644 --- a/rest_framework/reverse.py +++ b/rest_framework/reverse.py @@ -6,7 +6,7 @@ from django.utils.functional import lazy from rest_framework.settings import api_settings -def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra): +def reverse(viewname, args=None, kwargs=None, request=None, format=None, use_absolute_urls=api_settings.USE_ABSOLUTE_URLS, **extra): """ Same as `django.core.urlresolvers.reverse`, but optionally takes a request and returns a fully qualified URL, using the request to get the base URL. @@ -15,7 +15,7 @@ def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra kwargs = kwargs or {} kwargs['format'] = format url = django_reverse(viewname, args=args, kwargs=kwargs, **extra) - if api_settings.USE_ABSOLUTE_URLS: + if use_absolute_urls: assert request, "request is required for building absolute url" url = request.build_absolute_uri(url) return url diff --git a/rest_framework/tests/hyperlinkedserializers.py b/rest_framework/tests/hyperlinkedserializers.py index 24bf61bf8..b9120ccca 100644 --- a/rest_framework/tests/hyperlinkedserializers.py +++ b/rest_framework/tests/hyperlinkedserializers.py @@ -26,6 +26,14 @@ class PhotoSerializer(serializers.Serializer): return Photo(**attrs) +class PhotoUrlSerializer(PhotoSerializer): + url = serializers.HyperlinkedIdentityField(view_name='photoswithabsoluteurls-detail', use_absolute_urls=True) + + class Meta: + model = Photo + use_absolute_urls = False + + class BasicList(generics.ListCreateAPIView): model = BasicModel model_serializer_class = serializers.HyperlinkedModelSerializer @@ -74,6 +82,16 @@ class AlbumDetail(generics.RetrieveAPIView): model = Album +class PhotoUrlList(generics.ListAPIView): + model = Photo + serializer_class = PhotoUrlSerializer + + +class PhotoUrlDetail(generics.RetrieveAPIView): + model = Photo + serializer_class = PhotoUrlSerializer + + class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView): model = OptionalRelationModel model_serializer_class = serializers.HyperlinkedModelSerializer @@ -90,6 +108,8 @@ urlpatterns = patterns('', url(r'^comments/(?P\d+)/$', BlogPostCommentDetail.as_view(), name='blogpostcomment-detail'), url(r'^albums/(?P\w[\w-]*)/$', AlbumDetail.as_view(), name='album-detail'), url(r'^photos/$', PhotoListCreate.as_view(), name='photo-list'), + url(r'^photos-with-absolute-urls/$', PhotoAbsoluteUrlList.as_view(), name='photoswithabsoluteurls-list'), + url(r'^photos-with-absolute-urls/(?P<pk>\d+)/$', PhotoAbsoluteUrlDetail.as_view(), name='photoswithabsoluteurls-detail'), url(r'^optionalrelation/(?P<pk>\d+)/$', OptionalRelationDetail.as_view(), name='optionalrelationmodel-detail'), ) @@ -260,3 +280,37 @@ class TestOptionalRelationHyperlinkedView(TestCase): data=json.dumps(self.data), content_type='application/json') self.assertEqual(response.status_code, status.HTTP_200_OK) + + +class TestUrlOptionsView(TestCase): + urls = 'rest_framework.tests.hyperlinkedserializers' + + def setUp(self): + """ + Create a album and photos + """ + self.album = Album.objects.create(title="Test album") + items = ['beach', 'sunset', 'moon'] + for item in items: + Photo(description=item, album=self.album).save() + self.objects = Photo.objects + self.data = [ + { + 'url': '/photos-with-absolute-urls/%d/' % obj.id, + 'description': obj.text, + 'album_url': 'http://testserver/optionalrelation/%d/' % obj.album + } + for obj in self.objects.all() + ] + self.list_view = PhotoUrlList.as_view() + self.detail_view = PhotoUrlDetail.as_view() + + def test_get_detail_view(self): + """ + GET requests to RetrieveAPIView with optional relations should return None + for non existing relations. + """ + request = factory.get('/photos-with-absolute-urls/1') + response = self.detail_view(request) + self.assertEquals(response.status_code, status.HTTP_200_OK) + self.assertEquals(response.data, self.data[0:2]) \ No newline at end of file