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

使用Django+DRF开发API时POST请求出现AttributeError问题求助

嘿,我看到你在用Django和DRF开发基础API时,POST请求碰到了棘手的500错误,咱们来一步步搞定它!

先揪出直接报错的原因

你在处理POST请求时写了data = JSONParser().parse(request.body),但DRF的JSONParser.parse()方法需要的是类文件流对象,而request.body是原生的bytes类型,根本没有read()方法——这就是你看到AttributeError: 'bytes' object has no attribute 'read'的核心原因。

不过其实还有几个小细节需要调整,咱们一起修正:

1. 丢掉手动解析,用DRF自带的request.data(最省心的方式)

既然用了DRF,它已经帮你封装好了请求解析、内容协商这些繁琐工作,完全不需要自己调用JSONParser。修改你的views.py代码:

from rest_framework.response import Response
from rest_framework import status

def user_list(request):
    """ List all code users, or create a new user. """
    if request.method == 'GET':
        users = Users.objects.all()  # 用默认的objects管理器更规范,除非你有自定义需求
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)  # DRF的Response会自动处理格式和状态码
    elif request.method == 'POST':
        # 直接用request.data,DRF已经帮你解析好请求体了
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这里用DRF的Response替代Django原生的JsonResponse更符合REST API的规范,它会自动根据请求头返回合适的内容类型(比如JSON、XML等)。

2. 修复Serializer里的id字段问题

你的UserSerializer里把id定义成了普通的IntegerField,但Model里的id是自增主键(AutoField),创建用户时不需要客户端传入这个值,所以必须把它设为read_only=True,否则客户端不传id会触发校验错误:

class UserSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)  # 标记为只读,创建时无需传入
    name = serializers.CharField(max_length=200)  # 和Model里的max_length保持一致,别用None
    email = serializers.CharField(max_length=200)
    position = serializers.CharField(max_length=15)
    
    def create(self, validated_data):
        # 用默认的objects管理器即可,除非你自定义了users管理器有特殊逻辑
        return Users.objects.create(**validated_data)
    
    def update(self, instance, validated_data):
        # 更新时也不需要修改主键id,所以删掉这行赋值
        instance.name = validated_data.get('name', instance.name)
        instance.email = validated_data.get('email', instance.email)
        instance.position = validated_data.get('position', instance.position)
        instance.save()
        return instance

另外,Serializer里的CharField建议和Model里的max_length保持一致,这样能提前拦截不符合长度要求的请求。

3. 优化Model的管理器(可选)

你的Users Model里显式定义了users = models.Manager(),其实Django默认会给每个Model生成objects管理器,如果你没有自定义管理器的特殊需求,完全可以删掉这行代码,直接用Users.objects.all()、Users.objects.create()等方法。

最后测试一下

修改完成后,用类似下面的JSON格式发送POST请求:

{
    "name": "张三",
    "email": "zhangsan@example.com",
    "position": "developer"
}

应该就能正常创建用户啦!

内容的提问来源于stack exchange,提问作者user12625513

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 17:17:58