diff options
| author | Tom Christie | 2013-06-17 15:09:36 +0100 |
|---|---|---|
| committer | Tom Christie | 2013-06-17 15:09:36 +0100 |
| commit | 4ad10949687c271fed930cd1142aa23cd8c20b2b (patch) | |
| tree | feb51d06c42246e30ce8ab38b2b5c932803d2f75 | |
| parent | a7a9e8728453cafe331081cbf77ef42f8b9e1841 (diff) | |
| download | django-rest-framework-4ad10949687c271fed930cd1142aa23cd8c20b2b.tar.bz2 | |
HyperlinkedModelSerializer supports overriding of 'url' field. Closes #936
| -rw-r--r-- | rest_framework/serializers.py | 43 | ||||
| -rw-r--r-- | rest_framework/tests/test_hyperlinkedserializers.py | 27 | ||||
| -rw-r--r-- | tmp.html | 0 |
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 |
