当我试图创建一个新文档并与一系列对手方建立关联关系时,我会收到以下错误。
AttributeError:“dict”对象没有属性“_sa_instance_state”
我认为这个问题肯定存在于我的模型定义中,如果我删除了“backref=”文档作为交易对手关系,我会得到同样的错误,但在下一行,它试图添加文档。
数据库模型:
documents_counterparties = Table(
"documents_counterparties",
Base.metadata,
Column("document_id", ForeignKey("documents.id"), primary_key=True),
Column("counterparty_id", ForeignKey(
"counterparties.id"), primary_key=True)
)
class Document(Base):
__tablename__ = "documents"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
start_date = Column(Date)
end_date = Column(Date)
owner_id = Column(Integer, ForeignKey("users.id"))
owner = relationship("User", back_populates="documents")
counterparties = relationship(
"Counterparty", secondary=documents_counterparties, backref="documents"
)
解析器:
def create_document(db: Session, document: DocumentCreate, user_id: int):
db_document = models.Document(**document.dict(), owner_id=user_id) #<- errors here
db.add(db_document)
db.commit()
db.refresh(db_document)
return db_document
编辑:
DocumentCreate
class DocumentBase(BaseModel):
name: str
start_date: datetime.date
end_date: datetime.date
class DocumentCreate(DocumentBase):
counterparties: "list[CounterpartyClean]"
发布于 2022-07-27 08:26:04
正如@MatsLindh所提到的,问题在于类型。解决办法是:
How to use nested pydantic models for sqlalchemy in a flexible way
编辑以包括使用的解决方案:
对大安贝弗坦的信贷:
我给了每个嵌套的pydantic模型一个包含相应的SQLAlchemy模型的Meta类。就像这样:
from pydantic import BaseModel
from models import ChildDBModel, ParentDBModel
class ChildModel(BaseModel):
some_attribute: str = 'value'
class Meta:
orm_model = ChildDBModel
class ParentModel(BaseModel):
child: ChildModel
它允许我编写一个泛型函数,它循环遍历pydantic对象并将子模型转换为SQLAlchemy模型:
def is_pydantic(obj: object):
""" Checks whether an object is pydantic. """
return type(obj).__class__.__name__ == "ModelMetaclass"
def parse_pydantic_schema(schema):
"""
Iterates through pydantic schema and parses nested schemas
to a dictionary containing SQLAlchemy models.
Only works if nested schemas have specified the Meta.orm_model.
"""
parsed_schema = dict(schema)
for key, value in parsed_schema.items():
try:
if isinstance(value, list) and len(value):
if is_pydantic(value[0]):
parsed_schema[key] = [schema.Meta.orm_model(**schema.dict()) for schema in value]
else:
if is_pydantic(value):
parsed_schema[key] = value.Meta.orm_model(**value.dict())
except AttributeError:
raise AttributeError("Found nested Pydantic model but Meta.orm_model was not specified.")
return parsed_schema
parse_pydantic_schema
函数返回pydantic模型的字典表示,其中子模型被Meta.orm_model
中指定的相应SQLAlchemy模型替换。您可以使用此返回值一次创建父SQLAlchemy模型:
parsed_schema = parse_pydantic_schema(parent_model) # parent_model is an instance of pydantic ParentModel
new_db_model = ParentDBModel(**parsed_schema)
# do your db actions/commit here
如果需要,甚至可以将其扩展到自动创建父模型,但这要求您也为所有pydantic模型指定Meta.orm_model
。
https://stackoverflow.com/questions/73122511
复制相似问题