Ana içeriğe geç

Daha Büyük Uygulamalar - Birden Fazla Dosya

🌐 Translation by AI and humans

This translation was made by AI guided by humans. 🤝

It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖

You can improve this translation by helping us guide the AI LLM better.

English version

Bir uygulama veya web API geliştirirken, her şeyi tek bir dosyaya sığdırabilmek nadirdir.

FastAPI, tüm esnekliği korurken uygulamanızı yapılandırmanıza yardımcı olan pratik bir araç sunar.

Bilgi

Flask'ten geliyorsanız, bu yapı Flask'in Blueprints'ine denk gelir.

Örnek Bir Dosya Yapısı

Diyelim ki şöyle bir dosya yapınız var:

.
├── app
│   ├── __init__.py
│   ├── main.py
│   ├── dependencies.py
│   └── routers
│   │   ├── __init__.py
│   │   ├── items.py
│   │   └── users.py
│   └── internal
│       ├── __init__.py
│       └── admin.py

İpucu

Birden fazla __init__.py dosyası var: her dizinde veya alt dizinde bir tane.

Bu sayede bir dosyadaki kodu diğerine import edebilirsiniz.

Örneğin app/main.py içinde şöyle bir satırınız olabilir:

from app.routers import items
  • app dizini her şeyi içerir. Ayrıca boş bir app/__init__.py dosyası olduğu için bir "Python package" (bir "Python module" koleksiyonu) olur: app.
  • İçinde bir app/main.py dosyası vardır. Bir Python package'in (içinde __init__.py dosyası olan bir dizinin) içinde olduğundan, o package'in bir "module"’üdür: app.main.
  • Benzer şekilde app/dependencies.py dosyası da bir "module"’dür: app.dependencies.
  • app/routers/ adında bir alt dizin vardır ve içinde başka bir __init__.py dosyası bulunur; dolayısıyla bu bir "Python subpackage"’dir: app.routers.
  • app/routers/items.py dosyası app/routers/ package’i içinde olduğundan bir submodule’dür: app.routers.items.
  • app/routers/users.py için de aynı şekilde, başka bir submodule’dür: app.routers.users.
  • app/internal/ adında bir alt dizin daha vardır ve içinde başka bir __init__.py dosyası bulunur; dolayısıyla bu da bir "Python subpackage"’dir: app.internal.
  • Ve app/internal/admin.py dosyası başka bir submodule’dür: app.internal.admin.

Aynı dosya yapısı, yorumlarla birlikte:

.
├── app                  # "app" bir Python package'idir
   ├── __init__.py      # bu dosya, "app"i bir "Python package" yapar
   ├── main.py          # "main" module'ü, örn. import app.main
   ├── dependencies.py  # "dependencies" module'ü, örn. import app.dependencies
   └── routers          # "routers" bir "Python subpackage"idir
      ├── __init__.py  # "routers"ı bir "Python subpackage" yapar
      ├── items.py     # "items" submodule'ü, örn. import app.routers.items
      └── users.py     # "users" submodule'ü, örn. import app.routers.users
   └── internal         # "internal" bir "Python subpackage"idir
       ├── __init__.py  # "internal"ı bir "Python subpackage" yapar
       └── admin.py     # "admin" submodule'ü, örn. import app.internal.admin

APIRouter

Diyelim ki sadece kullanıcıları yönetmeye ayrılmış dosyanız /app/routers/users.py içindeki submodule olsun.

Kullanıcılarla ilgili path operation’ları, kodun geri kalanından ayrı tutmak istiyorsunuz; böylece düzenli kalır.

Ancak bu hâlâ aynı FastAPI uygulaması/web API’sinin bir parçasıdır (aynı "Python Package" içinde).

Bu module için path operation’ları APIRouter kullanarak oluşturabilirsiniz.

APIRouter Import Edin

FastAPI class’ında yaptığınız gibi import edip bir "instance" oluşturursunuz:

app/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}

APIRouter ile Path Operations

Sonra bunu kullanarak path operation’larınızı tanımlarsınız.

FastAPI class’ını nasıl kullanıyorsanız aynı şekilde kullanın:

app/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}

APIRouter’ı "mini bir FastAPI" class’ı gibi düşünebilirsiniz.

Aynı seçeneklerin hepsi desteklenir.

Aynı parameters, responses, dependencies, tags, vb.

İpucu

Bu örnekte değişkenin adı router. Ancak istediğiniz gibi adlandırabilirsiniz.

Bu APIRouter’ı ana FastAPI uygulamasına ekleyeceğiz; ama önce dependency’lere ve bir diğer APIRouter’a bakalım.

Dependencies

Uygulamanın birden fazla yerinde kullanılacak bazı dependency’lere ihtiyacımız olacağını görüyoruz.

Bu yüzden onları ayrı bir dependencies module’üne koyuyoruz (app/dependencies.py).

Şimdi, özel bir X-Token header'ını okumak için basit bir dependency kullanalım:

app/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")
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/dependencies.py
from fastapi import Header, HTTPException


async def get_token_header(x_token: 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")

İpucu

Örneği basit tutmak için uydurma bir header kullanıyoruz.

Ancak gerçek senaryolarda, entegre Security yardımcı araçlarını kullanarak daha iyi sonuç alırsınız.

APIRouter ile Başka Bir Module

Diyelim ki uygulamanızdaki "items" ile ilgili endpoint'ler de app/routers/items.py module’ünde olsun.

Şunlar için path operation’larınız var:

  • /items/
  • /items/{item_id}

Bu, app/routers/users.py ile aynı yapıdadır.

Ancak biraz daha akıllı davranıp kodu sadeleştirmek istiyoruz.

Bu module’deki tüm path operation’ların şu ortak özelliklere sahip olduğunu biliyoruz:

  • Path prefix: /items.
  • tags: (tek bir tag: items).
  • Ek responses.
  • dependencies: hepsinin, oluşturduğumuz X-Token dependency’sine ihtiyacı var.

Dolayısıyla bunları her path operation’a tek tek eklemek yerine APIRouter’a ekleyebiliriz.

app/routers/items.py
from fastapi import APIRouter, Depends, HTTPException

from ..dependencies import get_token_header

router = APIRouter(
    prefix="/items",
    tags=["items"],
    dependencies=[Depends(get_token_header)],
    responses={404: {"description": "Not found"}},
)


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"],
    responses={403: {"description": "Operation forbidden"}},
)
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"}

Her path operation’ın path’i aşağıdaki gibi / ile başlamak zorunda olduğundan:

@router.get("/{item_id}")
async def read_item(item_id: str):
    ...

...prefix’in sonunda / olmamalıdır.

Yani bu örnekte prefix /items olur.

Ayrıca, bu router içindeki tüm path operation’lara uygulanacak bir tags listesi ve ek responses da ekleyebiliriz.

Ve router’daki tüm path operation’lara eklenecek, her request için çalıştırılıp çözülecek bir dependencies listesi de ekleyebiliriz.

İpucu

path operation decorator’larındaki dependency’lerde olduğu gibi, path operation function’ınıza herhangi bir değer aktarılmayacağını unutmayın.

Sonuç olarak item path’leri artık:

  • /items/
  • /items/{item_id}

...tam da istediğimiz gibi olur.

  • Hepsi, içinde tek bir string "items" bulunan bir tag listesiyle işaretlenir.
    • Bu "tags", özellikle otomatik interaktif dokümantasyon sistemleri (OpenAPI) için çok faydalıdır.
  • Hepsi önceden tanımlı responses’ları içerir.
  • Bu path operation’ların hepsinde, öncesinde dependencies listesi değerlendirilip çalıştırılır.
    • Ayrıca belirli bir path operation içinde dependency tanımlarsanız, onlar da çalıştırılır.
    • Önce router dependency’leri, sonra decorator’daki dependencies, sonra da normal parametre dependency’leri çalışır.
    • Ayrıca scopes ile Security dependency’leri de ekleyebilirsiniz.

İpucu

APIRouter içinde dependencies kullanmak, örneğin bir grup path operation için kimlik doğrulamayı zorunlu kılmakta kullanılabilir. Dependency’leri tek tek her birine eklemeseniz bile.

Ek bilgi

prefix, tags, responses ve dependencies parametreleri (çoğu başka örnekte olduğu gibi) kod tekrarını önlemenize yardımcı olan, FastAPI’nin bir özelliğidir.

Dependency'leri Import Edin

Bu kod app.routers.items module’ünde, yani app/routers/items.py dosyasında duruyor.

Dependency function’ını ise app.dependencies module’ünden, yani app/dependencies.py dosyasından almamız gerekiyor.

Bu yüzden dependency’ler için .. ile relative import kullanıyoruz:

app/routers/items.py
from fastapi import APIRouter, Depends, HTTPException

from ..dependencies import get_token_header

router = APIRouter(
    prefix="/items",
    tags=["items"],
    dependencies=[Depends(get_token_header)],
    responses={404: {"description": "Not found"}},
)


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"],
    responses={403: {"description": "Operation forbidden"}},
)
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"}

Relative Import Nasıl Çalışır

İpucu

Import’ların nasıl çalıştığını çok iyi biliyorsanız, bir sonraki bölüme geçin.

Tek bir nokta ., örneğin:

from .dependencies import get_token_header

şu anlama gelir:

  • Bu module’ün (yani app/routers/items.py dosyasının) bulunduğu package içinden başla ( app/routers/ dizini)...
  • dependencies module’ünü bul (app/routers/dependencies.py gibi hayali bir dosya)...
  • ve oradan get_token_header function’ını import et.

Ama o dosya yok; bizim dependency’lerimiz app/dependencies.py dosyasında.

Uygulama/dosya yapımızın nasıl göründüğünü hatırlayın:


İki nokta .., örneğin:

from ..dependencies import get_token_header

şu anlama gelir:

  • Bu module’ün bulunduğu package içinden başla (app/routers/ dizini)...
  • üst (parent) package’e çık (app/ dizini)...
  • burada dependencies module’ünü bul (app/dependencies.py dosyası)...
  • ve oradan get_token_header function’ını import et.

Bu doğru şekilde çalışır! 🎉


Aynı şekilde, üç nokta ... kullansaydık:

from ...dependencies import get_token_header

şu anlama gelirdi:

  • Bu module’ün bulunduğu package içinden başla (app/routers/ dizini)...
  • üst package’e çık (app/ dizini)...
  • sonra bir üstüne daha çık (orada bir üst package yok; app en üst seviye 😱)...
  • ve orada dependencies module’ünü bul (app/dependencies.py dosyası)...
  • ve oradan get_token_header function’ını import et.

Bu, app/ dizininin üstünde, kendi __init__.py dosyası olan başka bir package’e işaret ederdi. Ama bizde böyle bir şey yok. Dolayısıyla bu örnekte hata verirdi. 🚨

Artık nasıl çalıştığını bildiğinize göre, uygulamalarınız ne kadar karmaşık olursa olsun relative import’ları kullanabilirsiniz. 🤓

Özel tags, responses ve dependencies Ekleyin

/items prefix’ini ya da tags=["items"] değerini her path operation’a tek tek eklemiyoruz; çünkü bunları APIRouter’a ekledik.

Ama yine de belirli bir path operation’a uygulanacak ek tags tanımlayabilir, ayrıca o path operation’a özel responses ekleyebiliriz:

app/routers/items.py
from fastapi import APIRouter, Depends, HTTPException

from ..dependencies import get_token_header

router = APIRouter(
    prefix="/items",
    tags=["items"],
    dependencies=[Depends(get_token_header)],
    responses={404: {"description": "Not found"}},
)


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"],
    responses={403: {"description": "Operation forbidden"}},
)
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"}

İpucu

Bu son path operation’da tag kombinasyonu şöyle olur: ["items", "custom"].

Ayrıca dokümantasyonda iki response da görünür: biri 404, diğeri 403.

Ana FastAPI

Şimdi app/main.py module’üne bakalım.

Burada FastAPI class’ını import edip kullanırsınız.

Bu dosya, uygulamanızda her şeyi bir araya getiren ana dosya olacak.

Mantığın büyük kısmı artık kendi module’lerinde yaşayacağı için ana dosya oldukça basit kalır.

FastAPI Import Edin

Normal şekilde bir FastAPI class’ı oluşturursunuz.

Hatta her APIRouter için olan dependency’lerle birleştirilecek global dependencies bile tanımlayabilirsiniz:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

APIRouter Import Edin

Şimdi APIRouter içeren diğer submodule’leri import ediyoruz:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

app/routers/users.py ve app/routers/items.py dosyaları aynı Python package’i olan app’in parçası olan submodule’ler olduğu için, onları "relative import" ile tek bir nokta . kullanarak import edebiliriz.

Import Nasıl Çalışır

Şu bölüm:

from .routers import items, users

şu anlama gelir:

  • Bu module’ün (yani app/main.py dosyasının) bulunduğu package içinden başla (app/ dizini)...
  • routers subpackage’ini bul (app/routers/ dizini)...
  • ve buradan items submodule’ünü (app/routers/items.py) ve users submodule’ünü (app/routers/users.py) import et...

items module’ünün içinde router adında bir değişken vardır (items.router). Bu, app/routers/items.py dosyasında oluşturduğumuz aynı değişkendir; bir APIRouter nesnesidir.

Sonra aynı işlemi users module’ü için de yaparız.

Ayrıca şöyle de import edebilirdik:

from app.routers import items, users

Bilgi

İlk sürüm "relative import"tur:

from .routers import items, users

İkinci sürüm "absolute import"tur:

from app.routers import items, users

Python Packages ve Modules hakkında daha fazlası için, Python'ın Modules ile ilgili resmi dokümantasyonunu okuyun.

İsim Çakışmalarını Önleyin

items submodule’ünü doğrudan import ediyoruz; sadece içindeki router değişkenini import etmiyoruz.

Çünkü users submodule’ünde de router adlı başka bir değişken var.

Eğer şöyle sırayla import etseydik:

from .routers.items import router
from .routers.users import router

users içindeki router, items içindeki router’ın üstüne yazardı ve ikisini aynı anda kullanamazdık.

Bu yüzden ikisini de aynı dosyada kullanabilmek için submodule’leri doğrudan import ediyoruz:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

users ve items için APIRouter’ları Dahil Edin

Şimdi users ve items submodule’lerindeki router’ları dahil edelim:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

Bilgi

users.router, app/routers/users.py dosyasının içindeki APIRouter’ı içerir.

items.router ise app/routers/items.py dosyasının içindeki APIRouter’ı içerir.

app.include_router() ile her bir APIRouter’ı ana FastAPI uygulamasına ekleyebiliriz.

Böylece o router içindeki tüm route’lar uygulamanın bir parçası olarak dahil edilir.

Teknik Detaylar

Aslında içeride, APIRouter içinde tanımlanan her path operation için bir path operation oluşturur.

Yani perde arkasında, her şey tek bir uygulamaymış gibi çalışır.

Ek bilgi

Router’ları dahil ederken performans konusunda endişelenmeniz gerekmez.

Bu işlem mikrosaniyeler sürer ve sadece startup sırasında olur.

Dolayısıyla performansı etkilemez. ⚡

Özel prefix, tags, responses ve dependencies ile Bir APIRouter Dahil Edin

Şimdi, kurumunuzun size app/internal/admin.py dosyasını verdiğini düşünelim.

Bu dosyada, kurumunuzun birden fazla proje arasında paylaştığı bazı admin path operation’larını içeren bir APIRouter var.

Bu örnekte çok basit olacak. Ancak kurum içinde başka projelerle paylaşıldığı için, bunu değiştirip prefix, dependencies, tags vs. doğrudan APIRouter’a ekleyemediğimizi varsayalım:

app/internal/admin.py
from fastapi import APIRouter

router = APIRouter()


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

Yine de bu APIRouter’ı dahil ederken özel bir prefix ayarlamak istiyoruz ki tüm path operation’ları /admin ile başlasın; ayrıca bu projede hâlihazırda kullandığımız dependencies ile güvene almak, tags ve responses eklemek istiyoruz.

Orijinal APIRouter’ı değiştirmeden, bu parametreleri app.include_router()’a vererek hepsini tanımlayabiliriz:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

Böylece orijinal APIRouter değişmeden kalır; yani aynı app/internal/admin.py dosyasını kurum içindeki diğer projelerle de paylaşmaya devam edebiliriz.

Sonuç olarak, uygulamamızda admin module’ündeki her bir path operation şunlara sahip olur:

  • /admin prefix’i.
  • admin tag’i.
  • get_token_header dependency’si.
  • 418 response’u. 🍵

Ancak bu sadece bizim uygulamamızdaki o APIRouter için geçerlidir; onu kullanan diğer kodlar için değil.

Dolayısıyla örneğin diğer projeler aynı APIRouter’ı farklı bir authentication yöntemiyle kullanabilir.

Bir Path Operation Dahil Edin

Path operation’ları doğrudan FastAPI uygulamasına da ekleyebiliriz.

Burada bunu yapıyoruz... sadece yapabildiğimizi göstermek için 🤷:

app/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)
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!"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

app/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)
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!"}

ve app.include_router() ile eklenen diğer tüm path operation’larla birlikte doğru şekilde çalışır.

Çok Teknik Detaylar

Not: Bu oldukça teknik bir detay; büyük ihtimalle direkt geçebilirsiniz.


APIRouter’lar "mount" edilmez; uygulamanın geri kalanından izole değildir.

Çünkü path operation’larını OpenAPI şemasına ve kullanıcı arayüzlerine dahil etmek istiyoruz.

Onları tamamen izole edip bağımsız şekilde "mount" edemediğimiz için, path operation’lar doğrudan eklenmek yerine "klonlanır" (yeniden oluşturulur).

Otomatik API Dokümanını Kontrol Edin

Şimdi uygulamanızı çalıştırın:

$ fastapi dev app/main.py

<span style="color: green;">INFO</span>:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Ve dokümanları http://127.0.0.1:8000/docs adresinde açın.

Tüm submodule’lerdeki path’leri, doğru path’ler (ve prefix’ler) ve doğru tag’lerle birlikte içeren otomatik API dokümanını göreceksiniz:

Aynı Router'ı Farklı prefix ile Birden Fazla Kez Dahil Edin

.include_router() ile aynı router’ı farklı prefix’ler kullanarak birden fazla kez de dahil edebilirsiniz.

Örneğin aynı API’yi /api/v1 ve /api/latest gibi farklı prefix’ler altında sunmak için faydalı olabilir.

Bu, muhtemelen ihtiyacınız olmayan ileri seviye bir kullanımdır; ancak gerekirse diye mevcut.

Bir APIRouter’ı Başka Birine Dahil Edin

Bir APIRouter’ı FastAPI uygulamasına dahil ettiğiniz gibi, bir APIRouter’ı başka bir APIRouter’a da şu şekilde dahil edebilirsiniz:

router.include_router(other_router)

router’ı FastAPI uygulamasına dahil etmeden önce bunu yaptığınızdan emin olun; böylece other_router içindeki path operation’lar da dahil edilmiş olur.