FastAPI provides a powerful mechanism for organizing your code through the use of routers and file structures. By using routers, you can divide your API into separate logical components and handle requests more efficiently. In this tutorial, we will explore how to use routers and how to organize your code using a file structure in FastAPI.
Creating a Router
To create a router in FastAPI, you can use the APIRouter class provided by FastAPI. This class allows you to define the routes, dependencies, and operations for a specific logical component of your API. Here’s how you can create a router in FastAPI:
from fastapi import APIRouter
router = APIRouter()
Defining Routes
Once you have created a router, you can define routes inside the router using the router.get(), router.post(), router.put(), router.delete(), and other methods provided by the router object. Here’s an example of how you can define a simple GET route inside a router:
@router.get("/")
async def read_root():
return {"message": "Hello, World!"}
Mounting a Router
To mount a router to your FastAPI application, you can use the include_router() method provided by your FastAPI app instance. Here’s how you can mount a router to your FastAPI application:
from fastapi import FastAPI
app = FastAPI()
app.include_router(router, prefix="/items", tags=["items"])
In the above code snippet, we are mounting the router to our FastAPI application with a prefix of "/items". This means that all routes defined inside the router will be prefixed with "/items". The tags parameter allows you to group routes in the automatic documentation generated by FastAPI.
File Structure
When building a larger FastAPI application, it’s essential to organize your code effectively using a file structure. A typical file structure for a FastAPI application might look like this:
app/
└── main.py
└── routers/
└── __init__.py
└── items.py
In this file structure, the main.py file is the entry point of the FastAPI application. The routers directory contains different router modules, with each module representing a logical component of the API. The init.py file inside the routers directory is used to initialize the router modules, while the items.py file contains the router for handling item-related routes.
In your main.py file, you can import and mount routers to your FastAPI application as follows:
from fastapi import FastAPI
from app.routers import items
app = FastAPI()
app.include_router(items.router, prefix="/items", tags=["items"])
By organizing your code using a file structure and routers, you can keep your FastAPI application modular, maintainable, and scalable. Routers help you divide your API into logical components, while a file structure helps you manage your codebase effectively. This tutorial has provided an overview of how to use routers and a file structure in FastAPI and highlighted their benefits in building robust APIs.
💡 Попробуй онлайн-тренажёр для подготовки к техническому собеседованию: https://clck.ru/3B5gwP 💡
Забирай роадмап изучения самого востребованного фреймворка на Python – FastAPI здесь: https://t.me/ArtemShumeikoBot
🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
почему ты изменил файлы не показывая на видео? в прошлом видео у тебя другая структура файлов, и тут ты сразу изменил не показывая как, и что изменил
почему-то алхимия выдала кортежи а не json/dict как на видео, помогла типизация
class OperationModel(BaseModel):
id: int
quantity: str
figi: str
instrument_type: str
date: datetime.datetime
type: str
@router.get('/{operation_type}', response_model=List[OperationModel])
async def get_specific_operation(operation_type:str , session: AsyncSession = Depends(get_async_session)):
query = select(operation).where(operation.c.type == operation_type)
result = await session.execute(query)
res = result.all()
return res
36:55 хах, неоднозначно получилось)
Про букву Z было смешно ))) Классный урок, спасибо !
36:55🤣 в этот момент они могут только появиться
28:47 Артëм, ты откуда взял данные для этой таблицы? Дай ссылку.
Прикольно, всю структуру проекта поменять и не показать по подробнее…
Сейчас в sqlalchemy что-то изменили, и теперь нельзя получить список словарей (объектов), написав result.all() (возвращается объект типа Sequence[Row[_TP]]). По этой теме даже появился вопрос на Стаковерфлоу, посвященный именно этому моменту именно из этого видео. Вместо result.all() теперь работает что-то вроде [dict(r._mapping) for r in result]. Надеюсь, с более сложной структурой это также будет работать.
P.s. увидел в комментариях более элегантное решение через result.mappings().all()
Легенда…
Артем спасибо за такие классные видео. Ты большой молодец.)
Спасибо за видео.
Добрый день, кто знает, как сделать валидацию существования внешнего ключа в БД через Pydantic? Чтоб если передаем Id внешнего ключа, которого нет в бд, не возвращала 500 ошибку.
урок про файловую структуру – "я изменил файловую структуру без вас потому что с вами было бы долго"
Ну плохой комментарий, так плохой комментарий😂, а так классная серия видосов, спасибо большое)
Добрый вечер Я вместо класс принял параметры от формы html, при попытке записать их в бд в запросе происходить ошибка, пробовал через словарь – ошибка, можете помочь, интересно, как вместо класса получать данные с формы. спасибо
@router.post("/submit-form")
async def submit_form(request: Request, session: AsyncSession = Depends(get_async_session)):
form = await request.form()
id = randint(10**4 , 10**5-1)
stmt = insert(towar).values(id=id,name=form.get('username'),
opus=form.get('texte'), price=form.get('price'),
count=form.get('tcount'), kategoriy=form.get('kategoriy') )
await session.execute(stmt)
await session.commit()
return {"status": "success"}
Добрый день. Подскажите почему на видео не было ошибки при получения get запроса(return result.all())? 29 минута. У меня была ошибка ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have dict attribute')]. Когда исправил на return result.mappings().all() ошибка пропала.
Спасибо
из своего опыта скажу – db инициализацию (создание таблиц, триггеров, функций, …) стоит выносить в отдельную папку
будет меньше забот при масштабировании проекта
Интересно на платном курсе тоже такие подставы есть, где лектор что-то делает сам, а ты потом должен догадаться что да как?