From 9bbc1cc403e3cf171710ae02255e2b7e6185f823 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 9 Oct 2012 17:49:04 +0100 Subject: [PATCH] Add flag in get_related_field --- docs/api-guide/serializers.md | 39 ++++++++++++++++------------------- rest_framework/serializers.py | 12 ++++++----- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index fff032413..47958fe31 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -120,7 +120,7 @@ Let's look at an example of serializing a class that represents an RGB color val assert(red < 256 and green < 256 and blue < 256) self.red, self.green, self.blue = red, green, blue - class ColourField(Field): + class ColourField(serializers.WritableField): """ Color objects are serialized into "rgb(#, #, #)" notation. """ @@ -138,7 +138,7 @@ By default field values are treated as mapping to an attribute on the object. I As an example, let's create a field that can be used represent the class name of the object being serialized: - class ClassNameField(Field): + class ClassNameField(serializers.WritableField): def field_to_native(self, obj, field_name): """ Serialize the object's class name, not an attribute of the object. @@ -158,7 +158,7 @@ As an example, let's create a field that can be used represent the class name of Often you'll want serializer classes that map closely to model definitions. The `ModelSerializer` class lets you automatically create a Serializer class with fields that corrospond to the Model fields. - class AccountSerializer(ModelSerializer): + class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account @@ -168,7 +168,7 @@ The `ModelSerializer` class lets you automatically create a Serializer class wit You can add extra fields to a `ModelSerializer` or override the default fields by declaring fields on the class, just as you would for a `Serializer` class. - class AccountSerializer(ModelSerializer): + class AccountSerializer(serializers.ModelSerializer): url = CharField(source='get_absolute_url', readonly=True) group = NaturalKeyField() @@ -183,7 +183,7 @@ When serializing model instances, there are a number of different ways you might Alternative representations include serializing using natural keys, serializing complete nested representations, or serializing using a custom representation, such as a URL that uniquely identifies the model instances. -The `PrimaryKeyField` and `NaturalKeyField` fields provide alternative flat representations. +The `PrimaryKeyRelatedField` and `HyperlinkedRelatedField` fields provide alternative flat representations. The `ModelSerializer` class can itself be used as a field, in order to serialize relationships using nested representations. @@ -197,20 +197,16 @@ If you only want a subset of the default fields to be used in a model serializer For example: - class AccountSerializer(ModelSerializer): + class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account exclude = ('id',) -The `fields` and `exclude` options may also be set by passing them to the `serialize()` method. - -**[TODO: Possibly only allow .serialize(fields=…) in FixtureSerializer for backwards compatability, but remove for ModelSerializer]** - ## Specifiying nested serialization The default `ModelSerializer` uses primary keys for relationships, but you can also easily generate nested representations using the `nested` option: - class AccountSerializer(ModelSerializer): + class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account exclude = ('id',) @@ -220,27 +216,28 @@ The `nested` option may be set to either `True`, `False`, or an integer value. When serializing objects using a nested representation any occurances of recursion will be recognised, and will fall back to using a flat representation. -The `nested` option may also be set by passing it to the `serialize()` method. - -**[TODO: Possibly only allow .serialize(nested=…) in FixtureSerializer]** - ## Customising the default fields used by a ModelSerializer - class AccountSerializer(ModelSerializer): + + + class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account def get_pk_field(self, model_field): - return Field(readonly=True) + return serializers.Field(readonly=True) def get_nested_field(self, model_field): - return ModelSerializer() + return serializers.ModelSerializer() - def get_related_field(self, model_field): - return NaturalKeyField() + def get_related_field(self, model_field, to_many=False): + queryset = model_field.rel.to._default_manager + if to_many: + return return serializers.ManyRelatedField(queryset=queryset) + return serializers.RelatedField(queryset=queryset) def get_field(self, model_field): - return Field() + return serializers.ModelField(model_field=model_field) [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 2141619f6..0faad703e 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -323,7 +323,9 @@ class ModelSerializer(Serializer): elif model_field.rel and nested: field = self.get_nested_field(model_field) elif model_field.rel: - field = self.get_related_field(model_field) + to_many = isinstance(model_field, + models.fields.related.ManyToManyField) + field = self.get_related_field(model_field, to_many=to_many) else: field = self.get_field(model_field) @@ -345,14 +347,14 @@ class ModelSerializer(Serializer): """ return ModelSerializer() - def get_related_field(self, model_field): + def get_related_field(self, model_field, to_many=False): """ Creates a default instance of a flat relational field. """ # TODO: filter queryset using: # .using(db).complex_filter(self.rel.limit_choices_to) queryset = model_field.rel.to._default_manager - if isinstance(model_field, models.fields.related.ManyToManyField): + if to_many: return ManyPrimaryKeyRelatedField(queryset=queryset) return PrimaryKeyRelatedField(queryset=queryset) @@ -446,7 +448,7 @@ class HyperlinkedModelSerializer(ModelSerializer): def get_pk_field(self, model_field): return None - def get_related_field(self, model_field): + def get_related_field(self, model_field, to_many): """ Creates a default instance of a flat relational field. """ @@ -458,6 +460,6 @@ class HyperlinkedModelSerializer(ModelSerializer): 'queryset': queryset, 'view_name': self._get_default_view_name(rel) } - if isinstance(model_field, models.fields.related.ManyToManyField): + if to_many: return ManyHyperlinkedRelatedField(**kwargs) return HyperlinkedRelatedField(**kwargs)