aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Christie2013-06-17 15:09:36 +0100
committerTom Christie2013-06-17 15:09:36 +0100
commit4ad10949687c271fed930cd1142aa23cd8c20b2b (patch)
treefeb51d06c42246e30ce8ab38b2b5c932803d2f75
parenta7a9e8728453cafe331081cbf77ef42f8b9e1841 (diff)
downloaddjango-rest-framework-4ad10949687c271fed930cd1142aa23cd8c20b2b.tar.bz2
HyperlinkedModelSerializer supports overriding of 'url' field. Closes #936
-rw-r--r--rest_framework/serializers.py43
-rw-r--r--rest_framework/tests/test_hyperlinkedserializers.py27
-rw-r--r--tmp.html0
3 files changed, 47 insertions, 23 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 11ead02e..5a8fd89f 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -904,34 +904,20 @@ class HyperlinkedModelSerializer(ModelSerializer):
_default_view_name = '%(model_name)s-detail'
_hyperlink_field_class = HyperlinkedRelatedField
- # Just a placeholder to ensure 'url' is the first field
- # The field itself is actually created on initialization,
- # when the view_name and lookup_field arguments are available.
- url = Field()
-
- def __init__(self, *args, **kwargs):
- super(HyperlinkedModelSerializer, self).__init__(*args, **kwargs)
+ def get_default_fields(self):
+ fields = super(HyperlinkedModelSerializer, self).get_default_fields()
if self.opts.view_name is None:
self.opts.view_name = self._get_default_view_name(self.opts.model)
- url_field = HyperlinkedIdentityField(
- view_name=self.opts.view_name,
- lookup_field=self.opts.lookup_field
- )
- url_field.initialize(self, 'url')
- self.fields['url'] = url_field
+ if 'url' not in fields:
+ url_field = HyperlinkedIdentityField(
+ view_name=self.opts.view_name,
+ lookup_field=self.opts.lookup_field
+ )
+ fields.insert(0, 'url', url_field)
- def _get_default_view_name(self, model):
- """
- Return the view name to use if 'view_name' is not specified in 'Meta'
- """
- model_meta = model._meta
- format_kwargs = {
- 'app_label': model_meta.app_label,
- 'model_name': model_meta.object_name.lower()
- }
- return self._default_view_name % format_kwargs
+ return fields
def get_pk_field(self, model_field):
if self.opts.fields and model_field.name in self.opts.fields:
@@ -966,3 +952,14 @@ class HyperlinkedModelSerializer(ModelSerializer):
return data.get('url', None)
except AttributeError:
return None
+
+ def _get_default_view_name(self, model):
+ """
+ Return the view name to use if 'view_name' is not specified in 'Meta'
+ """
+ model_meta = model._meta
+ format_kwargs = {
+ 'app_label': model_meta.app_label,
+ 'model_name': model_meta.object_name.lower()
+ }
+ return self._default_view_name % format_kwargs
diff --git a/rest_framework/tests/test_hyperlinkedserializers.py b/rest_framework/tests/test_hyperlinkedserializers.py
index 1894ddb2..129600cb 100644
--- a/rest_framework/tests/test_hyperlinkedserializers.py
+++ b/rest_framework/tests/test_hyperlinkedserializers.py
@@ -301,3 +301,30 @@ class TestOptionalRelationHyperlinkedView(TestCase):
data=json.dumps(self.data),
content_type='application/json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+
+class TestOverriddenURLField(TestCase):
+ def setUp(self):
+ class OverriddenURLSerializer(serializers.HyperlinkedModelSerializer):
+ url = serializers.SerializerMethodField('get_url')
+
+ class Meta:
+ model = BlogPost
+ fields = ('title', 'url')
+
+ def get_url(self, obj):
+ return 'foo bar'
+
+ self.Serializer = OverriddenURLSerializer
+ self.obj = BlogPost.objects.create(title='New blog post')
+
+ def test_overridden_url_field(self):
+ """
+ The 'url' field should respect overriding.
+ Regression test for #936.
+ """
+ serializer = self.Serializer(self.obj)
+ self.assertEqual(
+ serializer.data,
+ {'title': 'New blog post', 'url': 'foo bar'}
+ )
diff --git a/tmp.html b/tmp.html
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tmp.html