首页 > 解决方案 > 使用 JSON 可序列化枚举自动生成棉花糖模式

问题描述

创建与我的模型相同的棉花糖模式的日子已经一去不复返了。我找到了这个很好的答案,它解释了如何使用简单的装饰器从我的 SQA 模型中自动生成模式,所以我实现了它并替换了ModelSchema新的不推荐使用的模式SQLAlchemyAutoSchema

def add_schema(cls):
    class Schema(SQLAlchemyAutoSchema):
        class Meta:
            model = cls
    cls.Schema = Schema
return cls

这很好用......直到我撞到一个带着血腥的模特Enum

错误:Object of type MyEnum is not JSON serializable

我在网上搜索,发现这个有用的答案

但是我想将它作为装饰器的一部分来实现,以便它也可以自动生成。换句话说,我想在使用装饰器EnumField(TheEnum, by_value=True)生成模式时自动覆盖模型中的所有枚举;add_schema这样我就不必手动覆盖所有字段。

最好的方法是什么?

标签: pythonenumssqlalchemymarshmallow

解决方案


这是我的解决方案:

from marshmallow import validate
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
from marshmallow_enum import EnumField
from enum import Enum

def add_schema(cls):
    class Schema(SQLAlchemyAutoSchema):
        class Meta:
            model = cls

    fields = Schema._declared_fields

    # support for enum types
    for field_name, field_details in fields.items():
        if len(field_details.validate) > 0:
            enum_list = field_details.validate[0].choices
            enum_dict = {enum_list[i]: enum_list[i] for i in range(0, len(enum_list))}
            enum_clone = Enum(field_name.capitalize(), enum_dict)
            fields[field_name] = EnumField(enum_clone, by_value=True, validate=validate.OneOf(enum_list))

    cls.Schema = Schema
    return cls

这个想法是遍历 Schema 中的字段并找到那些具有验证的字段(通常是枚举)。从那里我们可以提取一个选项列表,然后可以用来从头开始构建一个枚举。最后,我们用新的EnumField.

无论如何,请随时改进答案!


推荐阅读