Use 'source' to determine which fields should be autogenerated
Opened this issue · 2 comments
It would be nice if one could use 'source' to change the name of a field in serialized data:
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
@dataclass
class MyDataclass:
model: MyModel
class MyDataclassSerializer(DataclassSerializer):
model_id = PrimaryKeyRelatedField(queryset=MyModel.objects.all(), source="model")
class Meta:
dataclass = MyDataclass
Right now this autogenerates another related field with the name 'model' and expects both to be in the serializer input data.
MyDataclassSerializer(data={"model_id": 1}).is_valid(raise_exception=True)
# raises rest_framework.exceptions.ValidationError: {'model': [ErrorDetail(string='This field is required.', code='required')]}
As a workaround I have to exclude the original like this:
class MyDataclassSerializer(DataclassSerializer):
model_id = PrimaryKeyRelatedField(queryset=MyModel.objects.all(), source="model")
class Meta:
dataclass = MyDataclass
exclude = ["model"]
Our use case is that we have both references and subserialized objects in our API, and we use '_id' as a postfix to identify references.
I'm not sure if suppressing the autogeneration of a field if another field uses it as source
would be a sensible default. I can imagine usecases where source
is used to add another representation, instead of replacing the default one all together, and it's also a breaking change. I'll have to check, but I also think that it'd be different behaviour from what DRF's built-in ModelSerializer
does.
DRF built-in serializers are a bit different since they allow partial models by default. But when I set __all__
as fields I indeed get the same behaviour.
from django.db import models
from rest_framework import serializers
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
class MyModel2(models.Model):
id = models.AutoField(primary_key=True)
model = models.ForeignKey(MyModel, on_delete=models.CASCADE)
class MyModelSerializer(serializers.ModelSerializer):
model_id = serializers.PrimaryKeyRelatedField(
queryset=MyModel.objects.all(), source="model"
)
class Meta:
model = MyModel2
fields = "__all__"
MyModel(id=1).save()
MyModelSerializer(data={"model_id": 1}).is_valid(raise_exception=True)
# raises rest_framework.exceptions.ValidationError: {'model': [ErrorDetail(string='This field is required.', code='required')]}
I think probably it is more common that you have one representation of a field by 'source' and don't want to autogenerate another one, but seems hard to change now.