I am trying to make a POST
request with an object for example this is how I send my request :
{
"title": "Haloween",
"body": " This is one of the greatest ones",
"grade_level": {
"id": 2,
"country": "UG"
},
"tags": [{"name": "Jamming"}]
}
So I wanted to post an object :
"grade_level": {
"id": 2,
"country": "UG"
}
and below is my Serializer I use :
class GradeClassSerializer(CountryFieldMixin, serializers.ModelSerializer):
"""GradeClass Serializer."""
class Meta:
model = ClassGrade
fields = ('id', 'grade', 'country', 'color_code', )
class PostSerializer(serializers.ModelSerializer):
"""Post Serializer"""
owner = UserProfile(read_only=True)
tags = TagSerializer(many=True)
comments = CommentSerializer(many=True, read_only=True)
slug = serializers.SlugField(read_only=True)
grade_level = GradeClassSerializer(many=False)
When I send the object grade_level
, I cant seem to receive it it only receives the the id :
def create(self, validated_data):
"""Create a blog post in a customized way."""
grade_level = validated_data.pop('grade_level', {})
status = validated_data.pop('status', '')
post = Post.objects.create(**validated_data,
owner=self.context['request'].user)
if grade_level:
grade = ClassGrade.objects.get(id=grade_level['id'])
post.grade_level = grade
post.save()
return post
When I make a request, this is what happens :
KeyError: 'id'
The object comes with only an country
without an id
.
This is what grade_level = validated_data.pop('grade_level', {})
prints :
OrderedDict([('country', 'UG')])
How can get the id
from the object.
NOTE:
- id is not flagged as read_only
EDIT :
In the views.py
below is the view :
class PostList(generics.ListCreateAPIView):
"""Blog post lists"""
queryset = Post.objects.filter(status=APPROVED)
serializer_class = serializers.PostSerializer
authentication_classes = (JWTAuthentication,)
permission_classes = (PostsProtectOrReadOnly, IsMentorOnly)
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data, context={
'request': request})
if serializer.is_valid():
serializer.save()
return response.Response(serializer.data,
status=status.HTTP_201_CREATED, )
return response.Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
Then models :
class ClassGrade(TimeStampedModel, models.Model):
"""ClassGrade is the class which Identifies the class or grade."""
grade = models.CharField(
_('Name'), max_length=150, null=True, blank=True)
country = CountryField()
color_code = ColorField(format='hexa', default='#33AFFF', null=True)
def __str__(self):
return self.grade
class Post(MainProcess, TimeStampedModel, models.Model):
"""Post model."""
title = models.CharField(_('Title'), max_length=100, blank=False,
null=False)
image = models.ImageField(_('Image'), upload_to='blog_images', null=True,
max_length=900)
body = models.TextField(_('Body'), blank=False)
description = models.CharField(_('Description'), max_length=400,
blank=True, null=True)
CodePudding user response:
By default, DRF treats the id(PrimaryKey) inside ModelSerializer as read-only. So to override this behavior u can try PrimaryKeyRelatedField
class GradeClassSerializer(CountryFieldMixin, serializers.ModelSerializer):
"""GradeClass Serializer."""
id = serializers.PrimaryKeyRelatedField(queryset=ClassGrade.objects.all(),
required=True)
class Meta:
model = ClassGrade
fields = ('id', 'grade', 'country', 'color_code', )
CodePudding user response:
So, by default, DRF will use the model fields in a ModelSerializer if you don’t define a field. Because the Id is an auto-created primary key (Django does this if you don’t explicitly override it) and Django assumes a primary key is read only, the id is omitted from the deserialized request