aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/serializers.py
diff options
context:
space:
mode:
authorTom Christie2012-10-04 06:07:26 -0700
committerTom Christie2012-10-04 06:07:26 -0700
commit42b3fdbdc26927e55713db31548a410870d82949 (patch)
treea1bb4780cd640da6f79fd0a107fa328271409ffe /rest_framework/serializers.py
parentad2149767bea4fcd07348ca77f6cad5719a44181 (diff)
parenteaebb397fa1ab9dfd11d347bbf583108c21e584b (diff)
downloaddjango-rest-framework-42b3fdbdc26927e55713db31548a410870d82949.tar.bz2
Merge pull request #279 from tomchristie/hyperlinked-relationships
Hyperlinked relationships
Diffstat (limited to 'rest_framework/serializers.py')
-rw-r--r--rest_framework/serializers.py69
1 files changed, 54 insertions, 15 deletions
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 03763824..ae0b3cdf 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -123,16 +123,8 @@ class BaseSerializer(Field):
# Get the explicitly declared fields
for key, field in self.fields.items():
ret[key] = field
- # Determine if the declared field corrosponds to a model field.
- try:
- if key == 'pk':
- model_field = obj._meta.pk
- else:
- model_field = obj._meta.get_field_by_name(key)[0]
- except:
- model_field = None
# Set up the field
- field.initialize(parent=self, model_field=model_field)
+ field.initialize(parent=self)
# Add in the default fields
fields = self.default_fields(serialize, obj, data, nested)
@@ -157,12 +149,12 @@ class BaseSerializer(Field):
#####
# Field methods - used when the serializer class is itself used as a field.
- def initialize(self, parent, model_field=None):
+ def initialize(self, parent):
"""
Same behaviour as usual Field, except that we need to keep track
of state so that we can deal with handling maximum depth and recursion.
"""
- super(BaseSerializer, self).initialize(parent, model_field)
+ super(BaseSerializer, self).initialize(parent)
self.stack = parent.stack[:]
if parent.opts.nested and not isinstance(parent.opts.nested, bool):
self.opts.nested = parent.opts.nested - 1
@@ -296,12 +288,22 @@ class ModelSerializerOptions(SerializerOptions):
self.model = getattr(meta, 'model', None)
-class ModelSerializer(RelatedField, Serializer):
+class ModelSerializer(Serializer):
"""
A serializer that deals with model instances and querysets.
"""
_options_class = ModelSerializerOptions
+ def field_to_native(self, obj, field_name):
+ """
+ Override default so that we can apply ModelSerializer as a nested
+ field to relationships.
+ """
+ obj = getattr(obj, self.source or field_name)
+ if obj.__class__.__name__ in ('RelatedManager', 'ManyRelatedManager'):
+ return [self.to_native(item) for item in obj.all()]
+ return self.to_native(obj)
+
def default_fields(self, serialize, obj=None, data=None, nested=False):
"""
Return all the fields that should be serialized for the model.
@@ -330,7 +332,7 @@ class ModelSerializer(RelatedField, Serializer):
field = self.get_field(model_field)
if field:
- field.initialize(parent=self, model_field=model_field)
+ field.initialize(parent=self)
ret[model_field.name] = field
return ret
@@ -339,7 +341,7 @@ class ModelSerializer(RelatedField, Serializer):
"""
Returns a default instance of the pk field.
"""
- return Field(readonly=True)
+ return Field()
def get_nested_field(self, model_field):
"""
@@ -373,7 +375,7 @@ class ModelSerializer(RelatedField, Serializer):
try:
return field_mapping[model_field.__class__]()
except KeyError:
- return Field()
+ return ModelField(model_field=model_field)
def restore_object(self, attrs, instance=None):
"""
@@ -396,3 +398,40 @@ class ModelSerializer(RelatedField, Serializer):
"""
self.object.save()
return self.object.object
+
+
+class HyperlinkedModelSerializerOptions(ModelSerializerOptions):
+ """
+ Options for HyperlinkedModelSerializer
+ """
+ def __init__(self, meta):
+ super(HyperlinkedModelSerializerOptions, self).__init__(meta)
+ self.view_name = getattr(meta, 'view_name', None)
+
+
+class HyperlinkedModelSerializer(ModelSerializer):
+ """
+ """
+ _options_class = HyperlinkedModelSerializerOptions
+ _default_view_name = '%(model_name)s-detail'
+
+ url = HyperlinkedIdentityField()
+
+ def __init__(self, *args, **kwargs):
+ super(HyperlinkedModelSerializer, self).__init__(*args, **kwargs)
+ if self.opts.view_name is None:
+ self.opts.view_name = self._get_default_view_name()
+
+ def _get_default_view_name(self):
+ """
+ Return the view name to use if 'view_name' is not specified in 'Meta'
+ """
+ model_meta = self.opts.model._meta
+ format_kwargs = {
+ 'app_label': model_meta.app_label,
+ 'model_name': model_meta.object_name.lower()
+ }
+ return self._default_view_name % format_kwargs
+
+ def get_pk_field(self, model_field):
+ return None