Django开发评论提交接口报错:BlogPostComment.blog_post需为BlogPost实例
问题原因
错误核心是给BlogPostComment.blog_post外键字段传入了字符串'Test',而Django外键字段要求必须传入对应关联的模型实例或者主键ID。同时存在序列化器使用不规范、字段传值逻辑冗余的问题:
- 不应该直接调用
serializer.create()传入原始的request.data,序列化器调用is_valid()校验通过后,只有validated_data是经过转换的合法数据 - 路由已经携带了博客的slug参数
url,完全可以后端直接查询对应的博文实例,不需要前端传递blog_post字段,避免传值错误 - 评论发布用户可以直接从请求对象
request.user获取,不需要前端传递,安全性更高
解决方案
1. 修复视图代码
添加DRF函数视图必要的装饰器,通过路由slug查询博文实例,后端注入关联字段:
from rest_framework.decorators import api_view from rest_framework.response import Response from django.shortcuts import get_object_or_404 from .models import BlogPost from .serializers import BlogPostCommentSerializer @api_view(['POST']) def CreateComment(request, url): # 用路由中的slug查询对应的博文实例,不存在直接返回404 blog_post = get_object_or_404(BlogPost, urlpattern=url) serializer = BlogPostCommentSerializer(data=request.data) # 校验不通过直接返回错误信息 if serializer.is_valid(raise_exception=True): # save方法支持传入额外关联字段,不需要前端传递 serializer.save(blog_post=blog_post, user=request.user) return Response(serializer.data, status=201) return Response(serializer.errors, status=400)
2. 简化序列化器代码
不需要前端传递关联字段,直接移除对应的字段定义:
class BlogPostCommentSerializer(serializers.ModelSerializer): class Meta: model = BlogPostComment fields = ['body'] # 仅保留需要用户输入的评论内容字段
3. 修复模型潜在报错
BlogPostComment的__str__方法直接拼接模型实例会触发类型错误,需要转成字符串:
class BlogPostComment(models.Model): # 原有字段不变 def __str__(self): return f"{str(self.blog_post)} | {str(self.user)}"
4. 前端AJAX请求调整
- 请求体仅需要传递
body字段即可,不需要再传blog_post、user字段 - 请求头需要携带CSRF令牌:Django默认开启CSRF校验,AJAX请求需要在请求头添加
X-CSRFToken字段,值从站点cookie的csrftoken字段获取 - 如果允许未登录用户提交评论,可自行调整
user外键的约束,设置null=True, blank=True即可
内容的提问来源于stack exchange,提问作者SnipeArt
相关产品推荐
相关产品推荐

