Reputation: 126
i have a somewhat tangled problem, I have the following models
class ModelA(models.Model):
name = models.CharField(max_length=64)
class ModelB(models.Model):
model_a = models.ForeignKey(ModelA, on_delete=models.CASCADE)
and the serializers
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = '__all__'
class ModelBSerializer(serializers.ModelSerializer):
terminal = ModelASerializer(read_only=True)
class Meta:
model = ModelB
fields = '__all__'
when I want to create a ModelB
object including the model_a_id it has 2 responses depending on whether I put the read_only=True
or False
I would like that when I try to create via POST
in an object of ModelB
I only have to send the mode_a_id
, but at the same time when I do a GET
it returns the serialized data of ModelASerializer
in the model_a
field.
If I put the read_only = True
it only works to receive the serialized data in GET
, but via POST
I cannot assign an id to model_a
in case of read_only=False
, I can't assign the id to that object either since it asks me for a dictionary, I imagine to create a new ModelA
Object, but I only want to assign one that already exists.
A solution may be to place the serializer with another variable name, but I would really like it to be the same for both POST
and GET
.
EDIT #1: examples of the json expected
make a GET for a simple view of ModelB object
{
"model_a" : {
"id": 1,
"name" : "foo"
}
}
and a POST like:
{
"model_a" : 1
}
that retrive of POST the same json as a GET:
{
"model_a" : {
"id": 1,
"name" : "foo"
}
}
Upvotes: 0
Views: 293
Reputation: 191
Just override to_representation()
method of your ModelBSerializer like the following.
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = '__all__'
class ModelBSerializer(serializers.ModelSerializer):
terminal = ModelASerializer(read_only=True)
class Meta:
model = ModelB
fields = '__all__'
def to_representation(self, instance):
pre_represented_data = super().to_representation(instance)
pre_represented_data['model_a'] = ModelASerializer(instance.model_a).data
return pre_represented_data
And if you seriously don't want the id
of ModelB in the GET call then just delete the key from pre_represented_data like following.
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = '__all__'
class ModelBSerializer(serializers.ModelSerializer):
terminal = ModelASerializer(read_only=True)
class Meta:
model = ModelB
fields = '__all__'
def to_representation(self, instance):
pre_represented_data = super().to_representation(instance)
pre_represented_data['model_a'] = ModelASerializer(instance.model_a).data
del pre_represented_data['id'] # deleting id of ModelB
return pre_represented_data
Upvotes: 1