如何用Python的marshmallow实现Post接口?新增对象失败且未返回ID
解决Post请求未写入数据库且未返回ID的问题
核心问题分析
- 未写入数据库:当前代码中Controller层仅调用了Serializer的
create方法,但该方法仅做了数据dump操作,完全没有触发Usecase层的数据库写入逻辑。 - 未返回ID:因为没有实际创建数据库对象,自然不会生成ID;即使创建了对象,当前序列化流程也未将带ID的实体转换为响应返回。
修复步骤
1. 修正Serializer的职责
Serializer应专注于输入验证(反序列化)和实体序列化,不要在其中处理业务逻辑。修改serializer.py:
from marshmallow import Schema, fields, ValidationError class ObjectSerializer(Schema): operatorId = fields.String(required=True) operator = fields.String(required=True) inaction = fields.Integer(required=False, default=1) # 与实体类字段类型保持一致 id = fields.Integer(required=False) createdAt = fields.Date(required=False) # 验证并反序列化输入数据 def validate_input(self, data: dict) -> dict: try: validated_data = super().load(data) return validated_data except ValidationError as err: return {'errors': err.messages} # 将实体序列化为响应字典 def serialize_entity(self, entity: 'ObjectEntity') -> dict: return super().dump(entity)
2. 修改Controller层,触发数据库写入
Controller需要先验证输入,再调用Usecase创建对象,最后序列化实体返回。修改controller.py:
from typing import Tuple from your_project.serializer import ObjectSerializer from your_project.usecase import ObjectUsecase from your_project.utils import HTTPStatus class ObjectController: def __init__(self, usecase: ObjectUsecase): self.usecase = usecase self.serializer = ObjectSerializer() def post(self, params: dict) -> Tuple[dict, int]: logger.info('Adding new object for params: %s', str(params)) # 1. 验证输入数据 validated_data = self.serializer.validate_input(params) if 'errors' in validated_data: logger.error('Error deserializing params: %s', str(validated_data['errors'])) return validated_data, HTTPStatus.BAD_REQUEST.value # 2. 调用Usecase写入数据库 try: entity = self.usecase.create( operatorId=validated_data['operatorId'], operator=validated_data['operator'] ) except Exception as e: logger.error('Failed to create object: %s', str(e)) return {'errors': ['Failed to create object']}, HTTPStatus.INTERNAL_SERVER_ERROR.value # 3. 序列化带ID的实体并返回 serialized_data = self.serializer.serialize_entity(entity) return serialized_data, HTTPStatus.CREATED.value # 创建成功标准返回201状态码
3. 确保Repository返回带ID的实体
确认lead_repo.create方法在写入数据库后,返回包含自动生成的id和createdAt的实体实例:
# 示例Repository实现 def create(self, operatorId: str, operator: str) -> ObjectEntity: # 执行数据库插入 cursor = self.db.execute( "INSERT INTO objects (operatorId, operator) VALUES (?, ?)", (operatorId, operator) ) self.db.commit() # 返回带ID的实体 return ObjectEntity( id=cursor.lastrowid, operatorId=operatorId, operator=operator, createdAt=datetime.date.today(), inaction=1 )
4. 修正Views层的请求解析(可选)
如果使用Flask等框架,需确保正确解析JSON请求体:
from flask import request, Response def post(self, *args, **kwargs) -> Response: try: query_data = request.get_json() except Exception as e: return Response(data={'errors': ['Invalid JSON']}, status=400) payload, status = self.controller.post(query_data) return Response(data=payload, status=status)
关键注意事项
- Marshmallow的
load用于验证输入(反序列化),dump用于对象转字典(序列化),不要混用。 - POST创建资源成功后,应返回
201 Created状态码,而非200 OK。 - 实体类与Serializer的字段类型需保持一致,避免类型不匹配错误。
内容的提问来源于stack exchange,提问作者pipka2
相关产品推荐
相关产品推荐

