[英]FastAPI DB Context
我想我誤解了 FastAPI 中如何使用依賴注入,特別是在 DB 會話的上下文中。
我當前的設置是 FastAPI、SqlAlchhemy 和 Alembic,雖然我自己編寫原始 SQL,pydantic 等,非常簡單。
我有基本的 CRUD 路由,它們直接與我的存儲庫層通信,並且一切正常。 在這些方法中,我能夠成功使用 DB 依賴項注入。 請參閱下面的示例代碼:
依賴關系
def get_database(request: Request) -> Database:
return request.app.state._db
def get_repository(Repo_type: Type[BaseRepository]) -> Callable:
def get_repo(db: Database = Depends(get_database)) -> Type[BaseRepository]:
return Repo_type(db)
return get_repo
示例通過 ID 路由獲取
@router.get("/{id}/", response_model=TablePub, name="Get Table by id")
async def get_table_by_id(
id: UUID, table_repo: TableRepository = Depends(get_repository(TableRepository))
) -> TableInDB:
table = await table_repo.get_table_by_id(id=id)
if not table:
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="No Table found with that id.")
return table
對應的存儲庫
from databases import Database
class BaseRepository:
def __init__(self, db: Database) -> None:
self.db = db
class TableRepository(BaseRepository):
async def get_table_by_id(self, *, id: UUID) -> TableInDB:
table = await self.db.fetch_one(
query=GET_TABLE_BY_ID_QUERY,
values={"id": id},
)
if not table:
return None
return TableInDB(**table)
現在我想開始做一些更復雜的操作,並想添加一個服務層來容納所有的業務邏輯。
構建它以便我可以重用我已經編寫的存儲庫的正確方法是什么? 例如,我想返回一個表的所有 Sales,但我需要先從數據庫中獲取表號,然后才能查詢 Sales 表。 該路由需要將 table_id 作為參數傳入 -> 服務層,我在其中通過 ID(使用現有存儲庫)獲取表 -> 從該對象中獲取表號,然后向需要表號作為參數。
到目前為止我所擁有的:
路線
@router.get("/{table_id}", response_model=SalesPub, name="Get Sale Entries by table id")
async def get_sales_by_table_id(
table_id: UUID = Path(..., title="ID of the Table to get Sales Entries for")):
response = await SalesService.get_sales_from_external_API(table_id=table_id)
return response
服務層“銷售服務”
async def get_sales_from_external_API(
table_id: UUID,
table_repo: TableRepository = Depends(get_repository(TableRepository))
) -> TableInDB:
table_data = await table_repo.get_table_by_id(id=table_id)
if table_data is None:
logger.info(f"No table with id:{table_id} could not be found")
table_number = table_data.number
client_id = table_data.client_id
sales = await salesGateway.call_external_API(table_number, client_id)
return sales
代碼在這里剎車table_data = await table_repo.get_table_by_id(id=table_id)
出現錯誤AttributeError: 'Depends' object has no attribute 'get_table_by_id'
我不明白的是,代碼與可以通過ID獲取表的路由方法幾乎相同? 將取決於對象TableRepository
確實有get_table_by_id
方法。 我做錯了什么,這是從數據庫操作中分離業務邏輯的最佳方式嗎?
提前致謝
我似乎已經找到了解決方案,盡管我不確定這是否是最好的方法。
Depends
模塊僅適用於 FastAPI 路由和依賴項。 我試圖在常規功能上使用它。
我需要使參數table_repo
成為Depends
的實例。 並將其作為參數傳遞給外部 API 調用函數。
@router.get("/table/{table_id}/", response_model=SalePub, name="Get Sales by table id")
async def get_sales_by_table_id(
table_id: UUID = Path(..., title="ID of the Table to get Sales Entries for"),
table_repo: TableRepository = Depends(get_repository(TableRepository))):
response = await get_sales_entries_from_pos(table_id=table_id, table_repo=table_repo)
return response
我預見的問題是,如果我有一個可能需要訪問 manny repos 的大型服務,我必須通過 Depends 在路由器上授予該訪問權限,這對我來說似乎有點奇怪。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.