我收到一个错误422 Unprocessable Entity' '{"detail": [{"loc": ["body"], "msg": "field required", "type": "value_error.missing"}]}
from typing import Optional, List, Any, Generator
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy import create_engine, Column, Integer, String, Numeric, Enum
from sqlalchemy.sql import text, select, func, column
from sqlalchemy.orm import Session, as_declarative, sessionmaker
from sqlalchemy.ext.declarative import declared_attr
from pydantic import BaseModel, condecimal
from enums import Colour
from config import settings
SQLALCHEMY_DATABASE_URL = settings.DATABASE_URL
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False,
autoflush=False,
bind=engine)
def get_db() -> Generator:
try:
db = SessionLocal()
yield db
finally:
db.close()
@as_declarative()
class Base:
id: Any
__name__: str
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()
class Pct(Base):
pid = Column(Integer, primary_key= True, nullable= False)
nm = Column(String, nullable= False)
p = Column(Numeric(70,67), nullable= False)
yr = Column(Integer, nullable= False)
color = Column(Enum(Colour), default=Colour.unknown)
kind = Column(String, nullable= False)
class PctBase(BaseModel):
pid: int
nm: str
p: condecimal(max_digits=70, decimal_places=67)
yr: int
color: Optional[Colour]
kind: str
def retrieve_pct(id: int, pct: PctBase, db: Session):
pct_object = Pct(**pct.dict())
pct_stmt = text('SELECT * FROM ptigree(:pid)', {'pid': id})
db.execute(pct_stmt)
db.commit()
return pct_object
router = APIRouter()
@router.get("/get/{id}", response_model= List[PctBase])
def read_pct(id: int, pct: PctBase, db: Session = Depends(get_db)):
pct = retrieve_pct(pct= pct, db= db, id= id)
return pct
我想发送的SQL函数ptigree
的id
由我的用户选择。ptigree
生成结果集(多行表,其中列:pid
、nm
、p
、yr
、color
、kind
),我希望API端点向我的用户显示这些结果。
我能够得到它的工作按照下面给出的建议。更改涉及1)使pct_recieve
使用SqlAlchemy获取实际结果:
def retrieve_pct(id: int, db: Session):
pct_func = func.ptigree(id).table_valued(
column("pid", Integer),
column("horse_nm", String),
column("p", Numeric(70,67)),
column("crop", Integer),
column("color", Enum(Colour)),
column("sex", String))
pct_stmt = select(pct_func)
pct_result = db.execute(pct_stmt)
db.commit
return pct_result
处理结果,Pydantic在read_pct
中逐行读取表:
@router.get("/get/{id}", response_model= List[PctBase])
def read_pct(id: int, db: Session = Depends(get_db)):
pct_result = retrieve_pct(id= id, db= db)
pct_objects = [PctBase(**row._asdict()) for row in pct_result]
return pct_objects
在PgAdmin中,我可以通过使用以下语句来验证SQL函数是否有效:
SELECT * FROM ptigree(some_integer);
它将返回预期的具有不同行数的五列表。
我花了一段时间查看文档和其他问题,但还没有成功地理解如何解决这个问题:
FastAPI如何访问接受用户输入并返回表的PostgreSQL自定义函数?
1条答案
按热度按时间vyswwuz21#
在FastAPI代码中,您似乎试图创建一个API端点,该端点通过用户输入调用PostgreSQL自定义函数(
ptigree
),并将结果作为表返回。但是,在尝试检索结果时遇到错误。要访问在FastAPI中返回表的PostgreSQL自定义函数,可以使用SQLAlchemy的
func
和select
函数。下面是应该可以工作的代码的更新版本:在此更新的代码中,
retrieve_pct
函数使用SQLAlchemy的func.ptigree
调用PostgreSQL自定义函数,并使用table_valued
指示它返回一个表。然后使用select(pct_func)
创建SQLAlchemy select语句,并使用db.execute(pct_stmt).fetchall()
获取所有结果。最后,它将获取的行转换为PctBase
对象,并从API端点返回它们。确保您有必要的导入(
enums
、config
),并且在config.py
文件中正确设置了数据库配置(settings.DATABASE_URL
)。请注意,您可能需要根据特定的数据库设置和
Colour
枚举的定义来调整代码。