Django - POST 更新多个表的端点。 Return 回复所有相关数据

Django - POST endpoint to update multiple tables. Return response with all relevant data

我下面有这个 POST 端点,它创建了一个 post。创建 post 时,请求可以附有视频和图像。正如您在下面看到的,序列化程序处理图像和视频之外的 post 数据,因为我需要对图像和视频进行验证。响应 return 是序列化的数据,但只有与图像和视频无关的所有内容。我还想要对 return 图像和视频 url 之类的东西的响应,uuid。如何使用新创建的 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

我这里有个功能

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'
        )

如果我可以将它应用到 Django 模型对象上,它将拥有我需要的一切。这仅适用于查询集。

为此,您可以使用 SerializerMethodField。这将是只读字段。

例如你的情况:-

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

让我知道这是否适合你。