首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SQLAlchemy 'dict‘对象没有属性'_sa_instance_state’

SQLAlchemy 'dict‘对象没有属性'_sa_instance_state’
EN

Stack Overflow用户
提问于 2022-07-26 11:24:00
回答 2查看 777关注 0票数 0

当我试图创建一个新文档并与一系列对手方建立关联关系时,我会收到以下错误。

AttributeError:“dict”对象没有属性“_sa_instance_state”

我认为这个问题肯定存在于我的模型定义中,如果我删除了“backref=”文档作为交易对手关系,我会得到同样的错误,但在下一行,它试图添加文档。

数据库模型:

代码语言:javascript
运行
复制
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"
    )

解析器:

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
class DocumentBase(BaseModel):
    name: str
    start_date: datetime.date
    end_date: datetime.date


class DocumentCreate(DocumentBase):
    counterparties: "list[CounterpartyClean]"
EN

Stack Overflow用户

发布于 2022-07-27 08:26:04

正如@MatsLindh所提到的,问题在于类型。解决办法是:

How to use nested pydantic models for sqlalchemy in a flexible way

编辑以包括使用的解决方案:

对大安贝弗坦的信贷:

我给了每个嵌套的pydantic模型一个包含相应的SQLAlchemy模型的Meta类。就像这样:

代码语言:javascript
运行
复制
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模型:

代码语言:javascript
运行
复制
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模型:

代码语言:javascript
运行
复制
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

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73122511

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档