Reputation: 7993
If I have something like this:
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
class Meta:
model = Snippet
fields = ('url', 'owner', 'title', 'code', 'linenos', 'language', 'style')
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = SnippetSerializer()
class Meta:
model = User
fields = ('url', 'username', 'snippets')
Then it will output all the fields defined in the SnippetSerializer. But I want to be able to do something like this:
snippets = SnippetSerializer(fields=('title', 'code'))
without having to do a duplicated SnippetSerializer like so:
class SnippetSerializerSmall(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
class Meta:
model = Snippet
fields = ('title', 'code')
Upvotes: 2
Views: 873
Reputation: 33921
There's some new documentation on dynamically modifying serializer fields that's just gone up on the site today...
http://django-rest-framework.org/api-guide/serializers.html#dynamically-modifiying-fields
Once a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the .fields
attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer.
For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so:
class DynamicFieldsModelSerializer(serializers.ModelSerializer):
"""
A ModelSerializer that takes an additional `fields` argument that
controls which fields should be displayed.
"""
def __init__(self, *args, **kwargs):
# Don't pass the 'fields' arg up to the superclass
fields = kwargs.pop('fields', None)
# Instatiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)
if fields:
# Drop any fields that are not specified in the `fields` argument.
allowed = set(fields)
existing = set(self.fields.keys())
for field_name in existing - allowed:
self.fields.pop(field_name)
This would then allow you to do the following:
>>> class UserSerializer(DynamicFieldsModelSerializer):
>>> class Meta:
>>> model = User
>>> fields = ('id', 'username', 'email')
>>>
>>> print UserSerializer(user)
{'id': 2, 'username': 'jonwatts', 'email': '[email protected]'}
>>>
>>> print UserSerializer(user, fields=('id', 'email'))
{'id': 2, 'email': '[email protected]'}
Upvotes: 4