英文:
How do I map Enum with SQLAlchemy to a Column that has special characters?
问题
我可以帮你解释这个问题并提供一些建议。问题出在你试图在 SQLAlchemy 中使用 enum 类型时,数据库接受的值与 Python Enum 中的值之间的不匹配。为了解决这个问题,你可以尝试以下步骤:
首先,你可以使用 SQLAlchemy 的 server_default
参数,以确保在插入数据时,Enum 值与数据库中的定义匹配。在你的 SQLAlchemy 模型中,尝试将 server_default
添加到 type
列上:
type = Column("type", Enum(TypeEnum), server_default=TypeEnum.Hired)
这将在插入数据时将默认值设置为 Hired
,以确保匹配数据库中的定义。
接下来,你应该使用 Python Enum 值而不是字符串值,以确保与数据库中的定义匹配。在读取 JSON 数据并将其转换为模型实例之前,确保你的 StatusSchema
中的 type
属性使用 Python Enum 值。例如:
from your_module import TypeEnumSchema
class StatusSchema(BaseModel):
id: str
type: TypeEnumSchema # values: TypeEnum.Hired, TypeEnum.Nonhired
这将确保你的数据与数据库中的 Enum 值匹配。
最后,检查你的 JSON 数据文件,确保它使用正确的 Python Enum 值。例如:
{
"data": [
{
"id": "63dd55b2-a99f-4e7b-985f-22c7bf80ab42",
"type": "hired"
},
{
"id": "41f98875-06c7-4cb1-b3d0-07f7ae192c0c",
"type": "non-hired"
}
]
}
确保在 JSON 文件中使用 Python Enum 值而不是字符串值。
通过采取这些步骤,你应该能够确保 Python Enum 值与数据库 Enum 值匹配,并且在将数据插入数据库时不会出现错误。
英文:
I have a database (in Postgresql) that has a table with a column of type enum. This enums receive only the values of 'Hired', 'Possible Hire' and 'Non-hired'.
The DDL would be:
CREATE TYPE enum_type AS ENUM('Hired', 'Possible Hire', 'Non-hired');
CREATE TABLE Status (
ID VARCHAR(63) PRIMARY KEY,
type enum_type NOT NULL
)
The class Enum in Python:
import enum
class TypeEnum(str, enum.Enum):
Hired = 'hired'
PossibleHire = 'possible hire'
Nonhired = 'non-hired'
And the SQLAlchemy model:
from sqlalchemy import Column, Enum, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class StatusModel(Base):
__tablename__ = "status"
id = Column(String(63), primary_key=True, index=True)
type = Column("type", Enum(TypeEnum))
But the problem is that I can't put 'Non-hired' in the variable name of a class.
I researched and found this article: https://www.notinventedhere.org/articles/python/how-to-use-strings-as-name-aliases-in-python-enums.html
That says that you need to use functional API of Enum.
So, I wrote the code:
TypeEnum = enum.Enum(
value="TypeEnum",
names=[
('Hired', 'hired'),
('Possible hire', 'possible hire'),
('Non-hired', 'non-hired'),
]
)
But with this functional syntax, the SQLAlchemy just passes the value of enum. For example, when StatusModel is initialized, I put 'hired' in the type and in Session.add arrives 'hired' instead of 'Hired'. In other words: If I pass "hired" it is rejected by the database as an invalid value for the enum. SQLAlchemy never interferes with the value being passed. Maybe the problem is how I'm passing the arguments in the column of the table? type = Column("type", Enum(TypeEnum))
I want to do an update to the problem:
I passed it the same Enum but from a schema in Pydantic
from enum import Enum
from pydantic import BaseModel
TypeEnumSchema = Enum(
value="TypeEnum",
names=[
('Hired', 'hired'),
('PossibleHire', 'possible hire'),
('Non-hired', 'non-hired'),
]
)
class StatusSchema(BaseModel):
id: str
type: TypeEnumSchema # values: hired, non-hired
class Config:
orm_mode = True
The data flow is:
I have this status_mock.json:
{
"data": [
{
"id": "63dd55b2-a99f-4e7b-985f-22c7bf80ab42",
"type": "hired"
},
{
"id": "41f98875-06c7-4cb1-b3d0-07f7ae192c0c",
"type": "non-hired"
},
]
}
Then I read it and take the data key:
data_object = read_json('./status_mock.json')["data"]
I get the list of data, pass each item to the schema and then to the model:
list_of_data: list[StatusSchema] = [StatusSchema(**item) for item in data_object]
records = StatusModel(id=data.id, type=data.type)
And then I write the code.
db.bulk_data(records)
def bulk_data(self, data):
with Session(self.engine) as session:
session.add_all(data)
session.commit()
But now it generates the next error:
sqlalchemy.exc.StatementError: (builtins.LookupError) 'TypeEnum.Hired' is not among the defined enum values. Enum name: typeenum. Possible values: Hired, Possible hired, Non-hired
答案1
得分: 0
将SQLAlchemy模型从以下功能性语法更改为:
class StatusModel(Base):
__tablename__ = "status"
id = Column(String(63), primary_key=True, index=True)
type = Column("type", Enum(TypeEnum))
更改为:
class StatusModel(Base):
__tablename__ = "status"
id = Column(String(63), primary_key=True, index=True)
type = Column("type", Enum(TypeEnum).value_callables)
在Enum()中添加.value_callables
。
英文:
Basically, with the functional syntax I had to change the SQLAlchemy model from:
class StatusModel(Base):
__tablename__ = "status"
id = Column(String(63), primary_key=True, index=True)
type = Column("type", Enum(TypeEnum))
To:
class StatusModel(Base):
__tablename__ = "status"
id = Column(String(63), primary_key=True, index=True)
type = Column("type", Enum(TypeEnum).value_callables)
Adding .value_callables
to the Enum()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论