簡體   English   中英

FastAPI 數據庫上下文

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM