Django rest framework one to one relation
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 !
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 generated
related name
in thefields
argument.For example:
class AlbumSerializer(serializers.ModelSerializer): class Meta: fields = ['track_set', ...]
Also, see the Django documentation on reverse relationships for more details.