如何在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
相关产品推荐
相关产品推荐

