I have this POST endpoint below that creates a post. When a post is created the request can be accompanied by video and images. As you can see below a serializer handles the post data outside of images and video, because I need to do validation on the image and video. The response returns the data serialized, but only everything not related to image and video. I'd like the response to also return stuff like image and video url, uuid. How can I do this with the newly created post_obj
?
view.py
@api_view(['POST'])
def POST_create_post(request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
try:
post_obj = serializer.save()
try:
if 'images' in request.FILES.keys():
for img in request.FILES.getlist('images'):
validate_image_upload(img)
Photo.objects.create(post=post_obj, image=img)
if 'video' in request.FILES.keys():
vid = request.FILES.get('video')
validate_video_upload(vid)
Video.objects.create(post=post_obj, video=vid)
except ValidationError as e:
return Response(dict(error=e,
user_message=error_message_generic),
status=status.HTTP_400_BAD_REQUEST)
except django.db.utils.InternalError as e:
return Response(dict(error=serializer.errors,
user_message=error_message_generic),
status=status.HTTP_400_BAD_REQUEST)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(dict(error=serializer.errors,
user_message=error_message_generic),
status=status.HTTP_400_BAD_REQUEST)
serializer.py
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('creator', 'body', 'uuid', 'created', 'updated_at')
models.py
class Photo(AbstractBaseModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
image = models.ImageField(upload_to=images_directory_path)
@property
def image_url(self):
return self.image.url
class Video(AbstractBaseModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
video = models.FileField(upload_to=videos_directory_path)
@property
def video_url(self):
return self.video.url
I have a function here
helper.py
def full_post_data_serializer(post_query_set: QuerySet):
"""
Returns post information in news feed form to include:
creator username, goal description, reply count, cheer count, photos
and video
Parameters:
post_query_set: Current Post model object query set
Returns:
serializer containing all data in query set serialized
for news feed
"""
query_set_annotated = post_query_set.annotate(
creator_username=F('creator__username'),
goal_description=F('join_goal__goal__description'),
goal_uuid=F('join_goal__goal__uuid'),
reply_count=Count('replypost', distinct=True),
cheer_count=Count('cheerpost', distinct=True)
).prefetch_related(
Prefetch('photo_set', Photo.objects.order_by('-created'))
)
return FullPostDataSerializer(query_set_annotated, many=True)
serializer.py
class FullPostDataSerializer(serializers.ModelSerializer):
image_url = serializers.SlugRelatedField(
source='photo_set', many=True, read_only=True, slug_field='image_url'
)
image_uuid = serializers.SlugRelatedField(
source='photo_set', many=True, read_only=True, slug_field='uuid'
)
video_url = serializers.SlugRelatedField(
source='video_set', many=True, read_only=True, slug_field='video_url'
)
video_uuid = serializers.SlugRelatedField(
source='video_set', many=True, read_only=True, slug_field='uuid'
)
goal_uuid = serializers.SlugField()
creator_username = serializers.SlugField()
reply_count = serializers.IntegerField()
cheer_count = serializers.IntegerField()
goal_description = serializers.SlugField()
class Meta:
model = Post
fields = (
'body', 'join_goal', 'created', 'creator_username', 'goal_description', 'reply_count', 'cheer_count',
'image_url', 'uuid', 'type', 'image_uuid', 'creator', 'video_url', 'video_uuid', 'goal_uuid'
)
If I could apply this to a Django model object that would have everything I need. This only works on a query set.
CodePudding user response:
For this purpose you can use SerializerMethodField. which will be read-only field.
for example in your case:-
class PostSerializer(serializers.ModelSerializer):
image_url = serializers.SerializerMethodField()
class Meta:
model = Post
fields = ('creator', 'body', 'uuid', 'created', 'updated_at' , 'image_url')
def get_image_url(self , obj):
# obj is Post object
# return image_url here
Let me know if this works for you.