APIView的post方法无法将数据存入数据库问题求助
问题分析与修复方案
核心问题点
- 外键传值类型错误:
request.data.get()拿到的是字符串格式的用户ID,但Follow模型的user和following_user是外键字段,需要传入User模型实例,直接传字符串会触发类型异常,导致数据无法写入数据库。 - 权限配置错误:DRF中权限配置属性是
permission_classes(复数),你写的permission_class(单数)会导致权限验证不生效。 - 冗余无效代码:post方法内部嵌套的
__str__方法完全无效,不会被执行。 - 不必要的save调用:
Follow.objects.create()本身已经完成数据库写入,无需额外调用follow.save()。 - 安全隐患:从请求数据中获取
user参数,可能被用户伪造(比如用自己的登录token却传别人的user ID),应该直接用当前登录用户request.user。 - 宽泛异常捕获:
except:会吞掉所有异常,无法定位具体错误原因(比如用户不存在、重复关注等)。
修复后的代码
视图层(FollowingView)
from django.db import IntegrityError from django.contrib.auth import get_user_model from rest_framework import status, permissions from rest_framework.response import Response from rest_framework.views import APIView from .models import Follow from .serializers import FollowSerializer User = get_user_model() class FollowingView(APIView): permission_classes = [permissions.IsAuthenticated] # 修正为复数形式 def post(self, request): following_user_id = request.data.get('to_user') if not following_user_id: return Response({"error": "缺少必填参数to_user"}, status=status.HTTP_400_BAD_REQUEST) try: # 将ID转换为User实例 following_user = User.objects.get(id=following_user_id) # 用当前登录用户作为关注主体,避免伪造 follow, created = Follow.objects.get_or_create( user=request.user, following_user=following_user ) if not created: return Response({"error": "已关注该用户"}, status=status.HTTP_400_BAD_REQUEST) serializer = FollowSerializer(follow) return Response(serializer.data, status=status.HTTP_201_CREATED) except User.DoesNotExist: return Response({"error": "目标用户不存在"}, status=status.HTTP_404_NOT_FOUND) except IntegrityError: return Response({"error": "关注关系已存在"}, status=status.HTTP_400_BAD_REQUEST)
可选优化:序列化器(FollowSerializer)
如果不想返回完整的User对象,可以将外键字段序列化为用户名或ID,更符合接口返回规范:
from rest_framework import serializers from .models import Follow class FollowSerializer(serializers.ModelSerializer): user = serializers.CharField(source='user.username') following_user = serializers.CharField(source='following_user.username') class Meta: model = Follow fields = ['user', 'following_user', 'date_followed']
关键修复说明
- 用
request.user获取当前登录用户,确保关注主体的合法性,避免参数伪造。 - 使用
get_or_create替代create,既避免重复创建关注关系,也能处理模型的唯一约束。 - 捕获具体异常(
User.DoesNotExist、IntegrityError),返回明确的错误信息,方便调试和前端处理。 - 将请求中的用户ID转换为User实例,满足外键字段的类型要求。
内容的提问来源于stack exchange,提问作者jdez
相关产品推荐
相关产品推荐

