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

如何在SQLModel+SQLite中处理枚举集合(无需多对多表)

在SQLModel+SQLite中存储枚举集合(无需多对多关联表)

针对你的需求,这里提供两种无需创建多对多表的实现方案,直接在单个字段中存储枚举集合:

方案一:使用JSON类型存储

利用SQLite对JSON的支持,将枚举集合序列化为字符串列表存储在JSON字段中,读取时再反序列化为枚举集合。

from enum import Enum
from sqlmodel import SQLModel, Field, Session, create_engine
from sqlalchemy import JSON
from typing import Set


class Colors(Enum):
    GREEN = "green"
    RED = "red"
    BLUE = "blue"
    YELLOW = "yellow"


class Fruit(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    colors: Set[Colors] = Field(sa_type=JSON)

    # 处理ORM对象转Pydantic模型时的枚举转换
    @classmethod
    def from_orm(cls, obj):
        fruit = super().from_orm(obj)
        if fruit.colors:
            fruit.colors = {Colors(color_str) for color_str in fruit.colors}
        return fruit

    # 处理Pydantic模型转字典时的枚举序列化
    def dict(self, **kwargs):
        data = super().dict(**kwargs)
        if data.get("colors"):
            data["colors"] = [color.value for color in data["colors"]]
        return data


# 测试示例
engine = create_engine("sqlite:///fruit.db")
SQLModel.metadata.create_all(engine)

with Session(engine) as session:
    apple = Fruit(name="Apple", colors={Colors.RED, Colors.GREEN})
    session.add(apple)
    session.commit()
    session.refresh(apple)
    print(apple.colors)  # 输出: {Colors.RED, Colors.GREEN}

优势:存储结构直观,支持SQLite的JSON查询语法(比如WHERE json_extract(colors, '$[*]') LIKE '%red%'),适合需要基于集合内元素查询的场景。

方案二:使用分隔字符串存储

将枚举值的字符串用分隔符(比如逗号)拼接成单个字符串,存储在TEXT字段中,通过属性封装实现集合与字符串的转换。

from enum import Enum
from sqlmodel import SQLModel, Field, Session, create_engine
from typing import Set


class Colors(Enum):
    GREEN = "green"
    RED = "red"
    BLUE = "blue"
    YELLOW = "yellow"


class Fruit(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    # 实际存储的字符串字段
    colors_str: str = Field(default="")

    # 封装成集合属性供外部使用
    @property
    def colors(self) -> Set[Colors]:
        if not self.colors_str:
            return set()
        return {Colors(color_str) for color_str in self.colors_str.split(",")}

    @colors.setter
    def colors(self, value: Set[Colors]):
        self.colors_str = ",".join([color.value for color in value])


# 测试示例
engine = create_engine("sqlite:///fruit.db")
SQLModel.metadata.create_all(engine)

with Session(engine) as session:
    banana = Fruit(name="Banana", colors={Colors.YELLOW})
    session.add(banana)
    session.commit()
    session.refresh(banana)
    print(banana.colors)       # 输出: {Colors.YELLOW}
    print(banana.colors_str)   # 输出: "yellow"

优势:存储体积更小,读写性能略优;但需注意枚举值不能包含分隔符,查询时需用LIKE语法(比如WHERE colors_str LIKE '%yellow%'),精准度略逊于JSON方案。

内容的提问来源于stack exchange,提问作者Lucien Chardon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 01:00:09