Let's say I have simple Product
Django model:
class Product:
name = models.CharField(max_length=255, unique=True)
created_on = models.DateField()
I'm using Django Rest Framework to serialize this model. I'd like to break up created_on
into its own object (including the response from GET requests and the payload in POST requests):
{
"name": "MyProduct",
"created_on": {
"year": 2020,
"month": 1,
"day": 24
}
}
Here's what I have so far:
class DateSerializer(serializers.Serializer):
year = serializers.IntegerField()
month = serializers.IntegerField()
day = serializers.IntegerField()
def validate(data):
return datetime.date(data["year"], data["month"], data["day"])
class ProductSerializer(serialzers.ModelSerializer):
created_on = DateSerializer()
class Meta:
model = Friend
fields = ("name", "created_on")
def create(self, validated_data):
return Product.objects.create(**validated_data)
class ProductViewset(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
This approach works for the GET requests (that is, I get the json above). However, it doesn't work for POST requests (payload being the json above). The response is 400
status code with the message {'created_on': [ErrorDetail(string='This field is required.', code='required')]}
.
If I pass required=False
into DateSerializer
, I see self.initial_data
in the create
method is <QueryDict: {'name': ['MyProduct'], 'created_on': ['year', 'month', 'day']}>
. So the values disappear for some reason.
Any idea what I'm doing wrong here and how I can get this to work?
Figured it out, I need to set the content_type=application/json
header in the request. Otherwise it defaults to content_type=multipart/form-data
which flattens the payload to {'name': ['MyProduct'], 'created_on': ['year', 'month', 'day']}
.