5.2.19. Example: Big Application with Multiple Files#

5.2.19.1. File structure#

.
├── app                  # "app" is a Python package   ├── __init__.py      # this file makes "app" a "Python package"   ├── main.py          # "main" module, e.g. import app.main   ├── dependencies.py  # "dependencies" module, e.g. import app.dependencies   └── routers          # "routers" is a "Python subpackage"      ├── __init__.py  # makes "routers" a "Python subpackage"      ├── items.py     # "items" submodule, e.g. import app.routers.items      └── users.py     # "users" submodule, e.g. import app.routers.users   └── internal         # "internal" is a "Python subpackage"       ├── __init__.py  # makes "internal" a "Python subpackage"       └── admin.py     # "admin" submodule, e.g. import app.internal.admin

5.2.19.2. Routers#

Path operations related to your users/items separated from the rest of the code, to keep it organized.

Create the path operations for that module using APIRouter

For users: <Cách đơn giản>

%%writefile routers/users.py

from fastapi import APIRouter

router = APIRouter()


@router.get("/users/", tags=["users"])
async def read_users():
    return [{"username": "Rick"}, {"username": "Morty"}]


@router.get("/users/me", tags=["users"])
async def read_user_me():
    return {"username": "fakecurrentuser"}


@router.get("/users/{username}", tags=["users"])
async def read_user(username: str):
    return {"username": username}
Overwriting routers/users.py

For items: <Cách thông minh và add thêm config>

Sử dụng config để có thể cài đặt tất cả các đặc điểm chung cho tất cả các router

Hoàn toàn có thể add more config (đặc điểm riêng) cho từng loại router bằng cách như bình thường (xem ví dụ phía dưới)

%%writefile routers/items.py

from fastapi import APIRouter, Depends, HTTPException

from dependencies import get_token_header

router = APIRouter(
    prefix="/items", # tất cả các router khi chạy ở main đều có path đứng đầu là "items"
    tags=["items"], # tất cả các config đều có tag là items
    dependencies=[Depends(get_token_header)], # Extra responses
    responses={404: {"description": "Not found"}}, # they all need that X-Token dependency we created.
)


fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}


@router.get("/")
async def read_items():
    return fake_items_db


@router.get("/{item_id}")
async def read_item(item_id: str):
    if item_id not in fake_items_db:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"name": fake_items_db[item_id]["name"], "item_id": item_id}


@router.put(
    "/{item_id}",
    tags=["custom"], # add more tags
    responses={403: {"description": "Operation forbidden"}}, # add more responses
)
async def update_item(item_id: str):
    if item_id != "plumbus":
        raise HTTPException(
            status_code=403, detail="You can only update the item: plumbus"
        )
    return {"item_id": item_id, "name": "The great Plumbus"}
Writing routers/items.py

For admin: <Cách đơn giản>

Tuy nhiên sẽ tuỳ chỉnh phần config của nhóm routers này khi import vào main.py thay vì config trực tiếp trong file code

%%writefile internal/admin.py
from fastapi import APIRouter

router = APIRouter()


@router.post("/")
async def update_admin():
    return {"message": "Admin getting schwifty"}
Writing internal/admin.py

5.2.19.3. Dependencies#

Use a simple dependency to read a custom X-Token header

%%writefile dependencies.py

from typing import Annotated

from fastapi import Header, HTTPException


async def get_token_header(x_token: Annotated[str, Header()]):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")


async def get_query_token(token: str):
    if token != "jessica":
        raise HTTPException(status_code=400, detail="No Jessica token provided")
Overwriting dependencies.py

5.2.19.4. Main app#

  • Thay vì config routers trong file code của router đó, thì config router khi add router vào app chính

%%writefile main.py
from fastapi import Depends, FastAPI

from dependencies import get_query_token, get_token_header
from internal import admin
from routers import items, users

app = FastAPI(dependencies=[Depends(get_query_token)])


app.include_router(users.router)
app.include_router(items.router)

# config routers when add to app in main 
app.include_router(
    admin.router,
    prefix="/admin",
    tags=["admin"],
    dependencies=[Depends(get_token_header)],
    responses={418: {"description": "I'm a teapot"}},
)


@app.get("/")
async def root():
    return {"message": "Hello Bigger Applications!"}
Overwriting main.py

5.2.19.5. Run app#

Run in dev: fastapi dev main.py

Run in prod: fastapi run main.py