如何将JSON传入Serializer并存入Model?代码无报错却未入库
让我帮你一步步排查为什么数据没存入数据库的问题:
核心问题点
视图函数调用方式错误
你直接把普通字典audit_record传给AuditRecord函数,但Django的视图函数必须接收HttpRequest对象作为第一个参数。你传的字典根本不是合法的请求对象,导致serializer = SaveAuditRecordSerializer(data=request, partial=True)里的request完全不是包含待存数据的数据源,自然无法解析出正确字段。Serializer初始化参数错误
就算传了正确的HttpRequest对象,你也不该把整个request传给data参数——正确的做法是用request.data来获取请求体里的JSON/表单数据。你现在把整个请求对象当数据源,Serializer根本无法识别里面的字段值。字段名不匹配
你构造的字典里写的是audit_record['action'] = "car created",但你的HistoricalRecords模型里对应的字段是car,这明显是笔误,就算前面逻辑都对,这个字段也存不进去。视图返回逻辑误导
不管Serializer验证成功还是失败,你都返回status.HTTP_201_CREATED,这会让你误以为操作成功了。实际上验证失败时应该返回status.HTTP_400_BAD_REQUEST,这样才能看到具体的错误信息。
正确的实现方式
建议把记录保存的逻辑抽成独立工具函数(视图是给HTTP请求用的,内部调用用工具函数更合理):
1. 新建工具函数(复用保存逻辑)
# record/utils.py(新建工具文件) from .models import HistoricalRecords from .serializer import SaveAuditRecordSerializer def save_audit_record(data): serializer = SaveAuditRecordSerializer(data=data) # 开启raise_exception可以直接抛出验证错误,方便调试 if serializer.is_valid(raise_exception=True): serializer.save() return True return False
2. 修正原视图函数(处理HTTP请求)
# record/views.py from rest_framework.response import Response from rest_framework import status from .serializer import SaveAuditRecordSerializer def AuditRecord(request): # 仅处理POST请求 if request.method == 'POST': serializer = SaveAuditRecordSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(status=status.HTTP_201_CREATED) # 验证失败返回400和错误信息 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # 非POST请求返回方法不允许 return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
3. 在其他应用中调用工具函数
from datetime import datetime from record.utils import save_audit_record # 其他应用视图中的代码 audit_record = {} audit_record['user'] = request.user.id # ForeignKey字段传用户ID或对象都可以,传ID更稳妥 audit_record['role'] = "Role" audit_record['model'] = "M" audit_record['torque'] = 22222 audit_record['car'] = "car created" # 修正字段名,和模型对应 # date_time字段有默认值,不需要手动传,如需自定义可以传iso格式字符串 # audit_record['date_time'] = datetime.now().isoformat() try: save_audit_record(audit_record) except Exception as e: # 可添加日志或错误处理逻辑 print(f"保存审计记录失败:{e}")
额外提示
如果user字段需要关联当前登录用户,更安全的做法是在Serializer的save方法中自动注入,避免手动传参出错:
# record/serializer.py class SaveAuditRecordSerializer(serializers.ModelSerializer): class Meta: model = HistoricalRecords fields = ('user', 'role', 'model', 'torque', 'car', 'date_time') def save(self, **kwargs): # 从上下文中获取当前用户 kwargs['user'] = self.context['request'].user return super().save(**kwargs)
此时调用时就不需要在audit_record里传user字段了。
内容的提问来源于stack exchange,提问作者ashfak

