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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:02:40