Django Rest Framework提交表单时填充用户字段报错解决
问题解决:Django DRF自动填充提交用户失败(AnonymousUser错误)
问题背景
开发Django+React应用时,使用DRF构建API,希望表单的submittedUser字段自动记录当前登录用户,但提交时出现错误:
Cannot assign "<django.contrib.auth.models.AnonymousUser object at 0x7f94a584dd80>": "entry.submittedUser" must be a "User" instance.
相关代码如下:
models.py
class User(AbstractUser): pass class entry(models.Model): title = models.CharField(max_length=600) submittedUser = models.ForeignKey('User',blank=True,null=True, on_delete=models.CASCADE, related_name='submitteduser')
serializers.py
class EntryFormSerializer(serializers.ModelSerializer): class Meta: model = entry fields = ['id','title', 'submittedUser']
views.py
class EntryFormViewSet(APIView): permission_classes = [AllowAny] authentication_classes = [TokenAuthentication] parser_classes = [MultiPartParser, FormParser, JSONParser] @csrf_exempt def post(self, request, format=None): data = request.data serializer = EntryFormSerializer(data=data) if serializer.is_valid(): serializer.save(submittedUser = self.request.user) return Response(serializer.data,status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
表单页面视图(补充)
def formsPage(request): if request.user.is_authenticated: theUser = request.user theUserProfile = userInfo.objects.get(user = theUser.id) if theUserProfile.is_admin: return render(request, 'frontend/index.html') else: return render(request, "frontend/login.html", { "message": " login to continue" }) else: return render(request, "frontend/login.html", { "message": "login to continue" })
解决方案
1. 限制API仅允许登录用户访问
当前视图设置permission_classes = [AllowAny],导致未登录用户也能发送请求,此时request.user是AnonymousUser,无法赋值给submittedUser。将权限类改为IsAuthenticated:
from rest_framework.permissions import IsAuthenticated class EntryFormViewSet(APIView): permission_classes = [IsAuthenticated] # 替换AllowAny authentication_classes = [TokenAuthentication] parser_classes = [MultiPartParser, FormParser, JSONParser] def post(self, request, format=None): # 移除@csrf_exempt,DRF已处理CSRF data = request.data serializer = EntryFormSerializer(data=data) if serializer.is_valid(): serializer.save(submittedUser=request.user) # 直接用request.user即可 return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
2. 优化序列化器,避免前端传入用户字段
将submittedUser设为只读字段,防止前端错误传入无效值,确保由后端自动赋值:
class EntryFormSerializer(serializers.ModelSerializer): class Meta: model = entry fields = ['id','title', 'submittedUser'] read_only_fields = ['submittedUser'] # 添加此行
3. 确保前端请求携带认证Token
React发送请求时,需在请求头中包含Token,示例:
// 假设token存储在localStorage中 const token = localStorage.getItem('authToken'); fetch('/api/entry/', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Token ${token}` // 必须携带此头 }, body: JSON.stringify({ title: '测试标题' }) })
4. 可选:兼容未登录用户的场景(如果需要)
若必须保留AllowAny权限,需在视图中判断用户是否已认证,再决定是否赋值:
def post(self, request, format=None): data = request.data serializer = EntryFormSerializer(data=data) if serializer.is_valid(): # 仅当用户已认证时赋值,否则留空 if request.user.is_authenticated: serializer.save(submittedUser=request.user) else: serializer.save() # 依赖模型的blank=True,null=True设置 return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
关键说明
AnonymousUser错误的核心原因是未登录用户访问了需要认证的API,或者前端未正确传递认证Token。- 表单页面的登录验证仅控制了页面访问,但API接口的权限验证独立,必须单独设置。
内容的提问来源于stack exchange,提问作者Mostafa Mohamed
相关产品推荐
相关产品推荐

