23👍
I just encountered the same problem, it would indeed be useful to make the response structure less tied to the underlying model structure. Here’s my take :
Reading is easy
Serializer fields have a source
parameter, which can take dotted names to traverse attributes.
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
Writing is … not officially supported
Validated data will show a nested structure, and the standard create and update methods will choke trying to assign a data dict to a OneToOneField.
The good news is that you can work around it by overriding create and update methods. Here’s an example with update :
class ABSerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = ['name', 'age', 'salary']
related_fields = ['b']
salary = serializer.IntegerField(source='b.salary') # this is your related_name
def update(self, instance, validated_data):
# Handle related objects
for related_obj_name in self.Meta.related_fields:
# Validated data will show the nested structure
data = validated_data.pop(related_obj_name)
related_instance = getattr(instance, related_obj_name)
# Same as default update implementation
for attr_name, value in data.items():
setattr(related_instance, attr_name, value)
related_instance.save()
return super(ABSerializer,self).update(instance, validated_data)
Of course, this example is very simplistic, doesn’t do any exception handling, and won’t work with more deeply nested objects… but you get the idea.
Another option
You could also create a read-write flavor of SerializerMethodField, which would consider both a getter and a setter, however that would probably end up being far more verbose in the end.
Hope that helps !
1👍
I know this is an old post but I came across this and after some research and reading through the Django Rest Framework documentation
So a quick search I found that you could use the related_name
parameter for reverse relationships as stated here:
reverse relationships are not automatically included by the
ModelSerializer
andHyperlinkedModelSerializer
classes. To include
a reverse relationship, you must explicitly add it to the fields list.For example:
class AlbumSerializer(serializers.ModelSerializer): class Meta: fields = ['tracks', ...]
You’ll normally want to ensure that you’ve set an appropriate
related_name
argument on the relationship, that you can use as the
field name.For example:
class Track(models.Model): album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE) ...
If you have not set a related name for the reverse relationship,
you’ll need to use the automatically generatedrelated name
in the
fields
argument.For example:
class AlbumSerializer(serializers.ModelSerializer): class Meta: fields = ['track_set', ...]
Also, see the Django documentation on reverse
relationships
for more details.
- [Django]-Django Blob Model Field
- [Django]-Case insensitive urls for Django?
- [Django]-Django : mysql : 1045, "Access denied for user