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