Stripp 数据库响应以适应 fastapi 中的模式

Stripp database response to fit in schema in fastapi

我开始用fastapi和Vue搭建一个wepapp。我从后端开始,试图从数据库中获取一些数据。作为 ORM,我使用 SQLAlchemy。我想要实现的是去除数据库对某些特定列的响应。

我对 web 应用程序的世界还很陌生,我也会欣赏一些好的资源。我发现开始这个话题有点困难。尽管有很多教程,但它们只介绍了如何启动一个基本站点,其余的留给文档。但是我你不习惯这个术语,在那里很容易迷路。

无论如何,我有这个测试设置:

我的数据库模型是

class System(Base):
__tablename__ = 'system'

id = Column(BIGINT(20), primary_key=True)
name = Column(String(200), nullable=False)
type = Column(String(200), nullable=False)
installed_power = Column(Float(asdecimal=True), nullable=False)
date_of_installation = Column(
    DateTime, nullable=False, server_default=text("current_timestamp()"))
last_changed = Column(DateTime, nullable=False, server_default=text(
    "current_timestamp() ON UPDATE current_timestamp()"))
site_id = Column(ForeignKey('site.id'), nullable=False, index=True)

site = relationship('Site')

我的架构是

class System(BaseModel):        
id: int
name: str
type: str
installed_power: int

在我的 main.py 我正在做这个

@app.get("/system", response_model=schemas.System)
def get_systems(db: Session = Depends(get_db)):
    query = crud.get_system(db)
    return query.all()

这个不行。错误显示 pydantic.error_wrappers.ValidationError: 1 validation error for System response value is not a valid dict (type=type_error.dict) 如果我将所有数据库列添加到架构中,它显然可以工作

我也尝试过类似的方法,但这也不起作用。

@app.get("/system", response_model=schemas.System)
def get_systems(db: Session = Depends(get_db)):
    query = crud.get_system(db)
    return query.all()
    res = []
    for row in query:
        system = schemas.System()
        system.id = row.id
        system.name = row.name
        system.type = row.type
        system.installed_power = row.installed_power
        res.append(system)
    return res

没有orm_mode

在您的第一个示例中,您的 response_model 需要一个架构 (System),但您将其发送 query.all(),其中 return 是一个 list 包含 类从你得到的模型。 (SQLAlchemy 没有 return 字典,这是 pydantic 默认情况下所期望的)。

所以,在这一点上,你必须做出选择,要么你的端点必须 return 一个对象,在这种情况下你不应该使用 query.all() 而像 query.one_or_none() .

或者您想要 return 对象列表,您的 response_model 应该是:

from typing import List

@app.get("/system", response_model=List[schemas.System])

剩下的就是格式化您的数据,使其与您的模式相对应。

只有一个数据的版本:

@app.get("/system", response_model=schemas.System)
def get_systems(db: Session = Depends(get_db)):
    query = crud.get_system(db).one_or_none()
    return schemas.System(id=query.id,name= query.name, type=query.type, installed_power=query.installed_power)

对于具有多个数据的版本:

from typing import List

def make_response_systems(query):
    result = []
    for data in query:
        result.append(schemas.System(id=query.id,name= query.name, type=query.type, installed_power=query.installed_power))
    return result

@app.get("/system", response_model=List[schemas.System])
def get_systems(db: Session = Depends(get_db)):
    query = crud.get_system(db).all()
    return make_response_systems(query)

有更多美观的方法可以做到这一点。但我认为上面的示例是理解其工作原理的好方法。

对于其余部分,您可以查看 orm_mode 的 pydantics 模型,您可以在 FastAPI 文档中找到它。

为了学习,FastAPI 文档非常完整且易于访问。

与 orm_mode

Pydantic 的 orm_mode 会告诉 Pydantic 模型读取数据,即使它不是字典,而是 ORM 模型(或任何其他具有属性的任意对象)。

class System(BaseModel):        
    id: int
    name: str
    type: str
    installed_power: int

    class Config:
        orm_mode = True
@app.get("/system", response_model=schemas.System)
def get_systems(db: Session = Depends(get_db)):
    query = crud.get_system(db).one_or_none()
    return query

fastapi 文档 orm_mode : https://fastapi.tiangolo.com/tutorial/sql-databases/?h=orm_mode#use-pydantics-orm_mode

根据 pydantic 文档

ORM Mode (aka Arbitrary Class Instances) Pydantic models can be created from arbitrary class instances to support models that map to ORM objects. To do this: The Config property orm_mode must be set to True. The special constructor from_orm must be used to create the model instance.

我们需要将 orm_mode 添加到架构配置中。

class System(BaseModel):        
  id: int
  name: str
  type: str
  installed_power: int
  
  class Config:
    orm_mode = True

参考:https://pydantic-docs.helpmanual.io/usage/models/#orm-mode-aka-arbitrary-class-instances