diff options
| author | Tom Christie | 2012-10-04 06:07:26 -0700 |
|---|---|---|
| committer | Tom Christie | 2012-10-04 06:07:26 -0700 |
| commit | 42b3fdbdc26927e55713db31548a410870d82949 (patch) | |
| tree | a1bb4780cd640da6f79fd0a107fa328271409ffe /rest_framework/serializers.py | |
| parent | ad2149767bea4fcd07348ca77f6cad5719a44181 (diff) | |
| parent | eaebb397fa1ab9dfd11d347bbf583108c21e584b (diff) | |
| download | django-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.py | 69 |
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 |
