部署PythonAnywhere的Django REST Framework POST/PUT请求报MultiValueDictKeyError
部署到PythonAnywhere后Django API POST/PUT请求出现MultiValueDictKeyError的排查与解决
问题核心分析
你遇到的MultiValueDictKeyError本质是请求未携带预期参数,或参数解析失败导致无法通过键直接取值。本地正常但部署后出错,大概率是请求内容类型不匹配或参数处理逻辑不严谨导致的,另外你的代码还存在严重安全问题,一并说明。
具体解决步骤
1. 严谨处理参数获取,避免直接用键访问字典
不管是request.data还是request.POST,直接用[]访问不存在的键都会抛出MultiValueDictKeyError。必须改用get()方法,并主动校验参数是否存在:
@api_view(['POST']) def register(request): # 用get方法获取参数,默认值为None name = request.data.get('name') email = request.data.get('email') password = request.data.get('password') address = request.data.get('address') # 校验必填参数是否为空 required_fields = {'name': name, 'email': email, 'password': password, 'address': address} for field_name, value in required_fields.items(): if not value: return Response({'Error': f'{field_name}参数必填'}, status=400) # 后续逻辑...
2. 确认请求的Content-Type是否正确
因为你用了api_view,Django REST Framework默认解析JSON格式请求,但如果前端发送的是表单数据(application/x-www-form-urlencoded或multipart/form-data),需要确保:
- 如果是JSON请求,必须在请求头中设置
Content-Type: application/json - 如果是表单提交,改用
request.POST.get()获取参数,但API接口推荐统一用JSON格式,避免混淆
3. 修复严重的SQL注入漏洞
你的代码直接拼接SQL字符串,存在极高的SQL注入风险,攻击者可通过构造参数篡改数据库。必须改用参数化查询:
try: cursor = connection.cursor() # 用%s作为占位符,参数放在元组中传入 cursor.execute( 'INSERT into buyer (name, email, password, address) values(%s, %s, %s, %s)', (name, email, password, address) ) return Response({"Message": "Registration successful."}) except db.OperationalError as e: return Response({'Error': str(e)}, status=400) except db.Error as e: return Response({'Error': str(e)}, status=400)
4. 修复密码明文存储问题(重要)
不要直接存储明文密码,用Django内置的密码加密函数:
from django.contrib.auth.hashers import make_password # 在插入数据库前加密密码 hashed_password = make_password(password) # 插入时用加密后的密码 cursor.execute( 'INSERT into buyer (name, email, password, address) values(%s, %s, %s, %s)', (name, email, hashed_password, address) )
额外排查点
- 检查PythonAnywhere上的Django版本是否和本地一致,版本差异可能导致request解析逻辑不同
- 查看PythonAnywhere的日志(控制台"Web"选项卡下),通过错误栈确认具体缺失的参数
内容的提问来源于stack exchange,提问作者HARSH BAMOTRA
相关产品推荐
相关产品推荐

