You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:02:43