Reputation: 4244
I feel like this is probably in the docs but I just can't seem to figure it out.
If I've got a serializer with a ForeignKey included in its fields
how do I exclude that FK when that serializer is nested in the related object?
class EmployerSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Employer
fields = ('name', 'person')
class PersonSerializer(serializers.HyperlinkedModelSerializer):
employers = EmployerSerializer()
class Meta:
model = Person
fields = ('name', 'employers')
depth = 1
When I hit the API at http://0.0.0.0:8000/person/1/
it lists something like:
{
"name": "Joe Blow",
"employers": {
"name": "Acme Inc."
"person": "http://0.0.0.0:8000/person/1/"
}
}
The "person" key for "employers" is self-referential and redundant, but only when the serializer is nested within the object it's referring to.
It seems like there should be an option to exclude it when the serializer is nested, but I can't figure it out.
Upvotes: 1
Views: 2631
Reputation: 2553
class DynamicFieldsModelSerializer(serializers.HyperlinkedModelSerializer):
"""
A HyperlinkedModelSerializer 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)
exclude = kwargs.pop('exclude', None)
# Instantiate 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)
if exclude:
# Drop fields that are specified in the `exclude` argument.
excluded = set(exclude)
for field_name in excluded:
try:
self.fields.pop(field_name)
except KeyError:
pass
extend EmployerSerializer with DynamicFieldsModelSerializer
class EmployerSerializer(DynamicFieldsModelSerializer):
class Meta:
model = Employer
fields = ('name', 'person')
class PersonSerializer(serializers.HyperlinkedModelSerializer):
employers = EmployerSerializer(exclude=('name',))
class Meta:
model = Person
fields = ('name', 'employers')
depth = 1
Upvotes: 7