在Django Rest Framework中调用PostgreSQL存储过程报错求助
解决DRF序列化器访问字段报错及存储过程调用问题
问题根源
你遇到的'Insertserialize' object has no attribute 'office_id'错误,是因为DRF的序列化器对象不能直接通过.属性名的方式获取字段值——验证后的字段数据存储在序列化器的validated_data字典中,需要从这里读取。
另外你的代码还存在几个隐藏问题:
- 存储过程调用缺少原生代码中的
email参数(对应request.user.userid) - 直接拼接SQL字符串存在严重的SQL注入风险
- 代码逻辑错误:两个
return语句顺序颠倒,第二个return永远不会执行
修正后的代码
views.py
from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import status from django.db import connection from .serializers import Insertserialize @api_view(['POST']) def saveitem(request): saveserialize = Insertserialize(data=request.data) if saveserialize.is_valid(): validated_data = saveserialize.validated_data # 获取当前用户的userid,对应原生代码中的email参数 user_email = request.user.userid # 使用参数化查询避免SQL注入 with connection.cursor() as cursor: cursor.execute( "SELECT add_clearance_item(%s, %s, %s, %s, %s, %s, %s)", [ validated_data['office_id'], validated_data['sem'], validated_data['sy'], validated_data['remarks'], validated_data['resolution'], user_email, validated_data['studid'] ] ) return Response(validated_data, status=status.HTTP_201_CREATED) # 验证失败时返回详细错误信息 return Response(saveserialize.errors, status=status.HTTP_400_BAD_REQUEST)
关键修改说明
- 正确获取序列化器字段值:用
saveserialize.validated_data['字段名']替代直接访问序列化器对象属性,这是DRF序列化器的标准用法。 - 补全存储过程参数:加入了原生代码中存在的
user_email参数,确保存储过程能正常执行。 - 避免SQL注入:改用参数化查询(
%s作为占位符,参数以列表形式传入),彻底解决SQL注入风险。 - 修正逻辑错误:将验证失败的
return语句移到if块外部,确保验证不通过时能返回错误响应。 - 自动管理游标:使用
with connection.cursor()上下文管理器,自动处理游标的创建和关闭,代码更安全简洁。
可选规范优化
序列化器类名建议遵循PEP8命名规范,改为InsertSerializer(首字母大写、驼峰命名),提升代码可读性:
class InsertSerializer(serializers.ModelSerializer): class Meta: model = ClearanceItem fields = ['office_id', 'sem', 'sy', 'remarks', 'resolution', 'studid']
内容的提问来源于stack exchange,提问作者Aaron Michael
相关产品推荐
相关产品推荐

