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
让我知道这是否适合你。
我下面有这个 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
让我知道这是否适合你。