Структура на проекта FastAPI и ръководства за най-добри практики

Последна актуализация: 12/27/2025
Автор: C SourceTrail
  • Изберете между оформления, базирани на файлов тип и такива, базирани на функции, въз основа на размера на проекта, архитектурата и нуждите на екипа, като поставите последователността на първо място.
  • Възползвайте се от типовите подсказки, Pydantic моделите и инжектирането на зависимости на FastAPI, за да поддържате маршрутизацията тънка, логиката модулна, а валидирането едновременно мощно и многократно използваемо.
  • Структурирайте сигурността, тестването, асинхронния вход/изход и конфигурацията като първокласни проблеми, така че мащабирането към производствена среда и множество екипи да не изисква пълно пренаписване.
  • Приемете ясни конвенции за именуване, миграция и инструменти, за да поддържате нарастващия парк от FastAPI монолит или микросървиси, който може да се поддържа във времето.

Най-добри практики за структура на проекти на FastAPI

Проектирането на чиста, мащабируема структура за FastAPI проект е едно от онези решения, които в началото изглеждат незначителни, но шест месеца по-късно променят живота ви напълно., когато кодовата база е нараснала, екипът се е разширил и се опитвате да проследите грешка в множество модули. Доброто оформление ускорява адаптацията, намалява регресиите и прави рефакторирането много по-лесно.

FastAPI ви дава огромна гъвкавост, но това също означава, че трябва активно да избирате и прилагате конвенции.В това ръководство ще съберем най-полезните идеи от реални, производствени FastAPI проекти и добре познати хранилища с най-добри практики, ще сравним основните оформления на проектите и ще видим как те взаимодействат с основните концепции на FastAPI, като например инжектиране на зависимости, валидиране, асинхронен вход/изход, тестване и внедряване.

Защо структурата на проекта е толкова важна във FastAPI

Солидната структура е гръбнакът, който поддържа FastAPI приложението разбираемо, докато то расте по размер и сложност.Без него, дори рамка с отлична ергономичност бързо се превръща в купчина ad-hoc модули, цикличен импорт и дублирана логика.

От инженерна гледна точка, структурата пряко влияе върху мащабируемосттаКогато модулите са отделени и отговорностите са ясни, можете да разделяте услуги, да въвеждате опашки или да мащабирате различни части от системата независимо, без да пренаписвате всичко.

Поддръжката е друга голяма победаКогато всеки маршрут, схема и модел на база данни има предвидим дом, разработчиците губят по-малко време в търсене на файлове и повече време в решаване на реални бизнес проблеми. Също така става по-лесно да се извършват прегледи на код, защото всички споделят един и същ ментален модел.

В екипните проекти, последователното оформление значително подобрява сътрудничествотоНовите служители могат да преценят къде да поставят нови функции, QA може да открие правилните входни точки за тестване, а DevOps може да разбере кои части са критични за стартиране на приложението (например къде се намира ASGI обектът на приложението и как е свързана базата данни).

Илюстрация на оформлението на папката FastAPI

Основни принципи за структуриране на FastAPI проекти

Преди да изберете оформление на папките, е полезно да се споразумеете за няколко принципа, които трябва да ръководят всяко решение за архитектура.Тези идеи се появяват многократно в успешни кодови бази на FastAPI.

Разделяне на грижите е първият стълб: съхранявайте маршрутизацията, постоянството, бизнес правилата и интеграционния код на различни места. Крайните точки трябва да оркестрират случаи на употреба, а не да вграждат SQL заявки, манипулиране на JSON и външни извиквания на услуги, всичко в една дълга функция.

Модулността е вторият стълбВместо един гигантски монолитен пакет, се стремете към по-малки, фокусирани модули или подпакети, които капсулират свързано поведение. Това значително улеснява повторното използване на части, тестването им изолирано и евентуалното им разделяне на микросървиси, ако е необходимо.

Инжектирането на зависимости е лепилото, което свързва тези модули без тясно свързване.Системата за зависимости на FastAPI ви позволява да декларирате от какво се нуждае даден маршрут или услуга (сесия на базата данни, конфигурация, удостоверен потребител и т.н.) и да позволите на рамката да го предостави, което е идеално за тестване и повторна употреба.

Самата тестваемост трябва да се третира като изискване от първокласен класАко структурата затруднява стартирането на приложението в паметта, презаписването на зависимостите и достигането на крайни точки с тестов клиент, или ще пропуснете тестовете, или ще се борите със собствената си архитектура. Добрата структура запазва страничните ефекти локални и пътищата импортируеми от тестовете.

Две доминиращи оформления на проекти на FastAPI: по тип файл срещу по функция

В екосистемата на FastAPI обикновено ще намерите две ясни семейства оформления: проекти, организирани по тип файл (рутери, модели, схеми, CRUD) и проекти, организирани по домейн или функция (авторизация, потребители, публикации, плащания и др.). Всеки един от тях се отличава в различен контекст.

Структура, базирана на файлов тип (рутери, схеми, модели, CRUD)

Подходът с файлов тип отразява начина, по който много официални примери и уроци въвеждат FastAPIГрупирате кода според неговата техническа роля: слой за маршрутизиране, пидантични схеми, модели на бази данни, CRUD операции, помощни програми и т.н.

Минималистично, но реалистично оформление може да изглежда така (съкратено за по-голяма яснота):

Примерно оформление: .├── app
│ ├── __init__.py
│ ├── main.py # FastAPI app initialization
│ ├── dependencies.py # shared dependencies
│ ├── routers
│ │ ├── __init__.py
│ │ ├── items.py # endpoints for items
│ │ └── users.py # endpoints for users
│ ├── crud
│ │ ├── item.py # item CRUD
│ │ └── user.py # user CRUD
│ ├── schemas
│ │ ├── item.py # pydantic models for items
│ │ └── user.py # pydantic models for users
│ ├── models
│ │ ├── item.py # ORM models for items
│ │ └── user.py # ORM models for users
│ ├── external_services
│ │ ├── email.py # email provider client
│ │ └── notification.py # push / notification client
│ └── utils
│ ├── authentication.py
│ └── validation.py
├── tests
│ ├── test_main.py
│ ├── test_items.py
│ └── test_users.py
├── requirements.txt
└── README.md

В този стил, всяка директория от най-високо ниво под app/ има една единствена отговорност, Например, routers/ описва HTTP входни точки, schemas/ декларира входни/изходни форми и models/ представляват таблици от база данни.

Това оформление е подходящо за малки до средни услуги или микросървиси.Домейнът обикновено е достатъчно тясен, така че разделянето по техническа роля да не създава триене. Повечето крайни точки използват един и същ ограничен набор от модели и само няколко екипа работят с кода едновременно.

Ключовите предимства на файловата структура включват много ниско когнитивно натоварване за начинаещи. и дърво на директории, което следва стриктно документацията на FastAPI. За някой, който изучава рамката, виждането на специален routers/ папка и schemas/ Папката често се усеща по-интуитивно, отколкото директното преминаване към пакетиране, управлявано от домейн.

Структура, ориентирана към функции или модули, под src/

С разрастването на проектите в монолити с много домейни, оформлението на файловите типове започва да се проваля.Получавате гигантски директории като например routers/ с десетки файлове, сложни междумодулни импорти и бизнес логика, разпръсната в несвързани пакети.

Алтернатива, която се мащабира по-добре, е структурата, базирана на характеристики или управлявана от домейн.Тук поставяте целия код за даден домейн в един подпакет: маршрути, схеми, модели, услуги, конфигурация и специфични за модула изключения.

Представително оформление, вдъхновено от популярни хранилища с най-добри практики, изглежда така:

Представително файлово дърво: fastapi-project
├── alembic/
├── src
│ ├── auth
│ │ ├── router.py # auth endpoints
│ │ ├── schemas.py # pydantic models
│ │ ├── models.py # DB models
│ │ ├── dependencies.py # auth-specific dependencies
│ │ ├── config.py # local configs
│ │ ├── constants.py # auth error codes / constants
│ │ ├── exceptions.py # auth-specific exceptions
│ │ ├── service.py # business logic
│ │ └── utils.py # helpers
│ ├── aws
│ │ ├── client.py
│ │ ├── schemas.py
│ │ ├── config.py
│ │ ├── constants.py
│ │ ├── exceptions.py
│ │ └── utils.py
│ ├── posts
│ │ ├── router.py
│ │ ├── schemas.py
│ │ ├── models.py
│ │ ├── dependencies.py
│ │ ├── constants.py
│ │ ├── exceptions.py
│ │ ├── service.py
│ │ └── utils.py
│ ├── config.py # global configs
│ ├── models.py # shared DB models
│ ├── exceptions.py # shared exceptions
│ ├── pagination.py # reusable pagination logic
│ ├── database.py # DB connection & session management
│ └── main.py # FastAPI app factory / entry point
├── tests
│ ├── auth
│ ├── aws
│ └── posts
├── templates
│ └── index.html
├── requirements
│ ├── base.txt
│ ├── dev.txt
│ └── prod.txt
├── .env
├── logging.ini
└── alembic.ini

В този свят, src/ е върхът на вътрешното дърво на приложениятаВсеки домейн, като auth or posts, се превръща почти в мини-услуга: тя носи свой собствен рутер, схеми, модели, константи, типове грешки и слой бизнес услуги.

Основното предимство е локалността на промяната: когато добавите нова функция към posts, рядко се налага да докосвате несвързан пакет. Тестовете могат да съществуват заедно с функциите си (например под tests/posts/), което насърчава по-високо покритие.

Тази структура е особено подходяща за монолитни приложения с много домейни и екипи, където искате да поддържате паралелна работа и да намалите конфликтите при сливане. Също така се съчетава добре с концепции за дизайн, управлявани от домейн, като ограничени контексти и агрегати.

Домейни и модули на FastAPI

Избор на правилното оформление за вашия FastAPI проект

Изборът между файлов тип и структура, базирана на функции, не е въпрос на правилно или грешно, а на съчетаване на вашата архитектура и очаквания за растеж.Малък вътрешен инструмент само с няколко крайни точки няма да се възползва особено от сложно оформление на домейна.

За микросървиси и API с тесен обхват, оформлението на файловите типове обикновено е по-просто.Всяка услуга често се фокусира върху една единствена отговорност (API за фактуриране, подател на известия, микроуслуга за отчитане) и разработчиците вече знаят интуитивно къде да поставят нови маршрути или схеми.

За по-големи монолити, разделянето по домейн почти винаги печели в дългосрочен план.Когато имате модули за профили, абонаменти, съдържание, плащания, анализи и други, поставянето на всеки рутер в една директория става хаотично. Групирането по функция запазва всеки сегмент от системата самостоятелен.

Също така, вземете предвид структурата на екипа сиАко един малък екип притежава цялата кодова база, поддържането на последователност може да е по-лесно с опростено оформление. Ако няколко екипа споделят монолита и всеки от тях притежава домейн, структурата, базирана на функции, им позволява да се движат по-бързо, без да си пречат взаимно.

Каквото и да изберете, постоянството е по-важно от точната форма на дървотоПромяната на оформлението по време на проекта е болезнена, така че инвестирането на малко размисъл в началото и написването на кратко ръководство за вътрешен стил ще се отплати по-късно.

Разбиране на самия FastAPI: какво структурирате

За да проектирате разумна структура, ви е необходим ясен ментален модел на това, което FastAPI всъщност прави за вас.В основата си FastAPI е ASGI уеб рамка, фокусирана върху изграждането на HTTP API с Python 3.7+, използвайки типови подсказки.

FastAPI се основава предимно на Pydantic за валидиране на данни и сериализацияТой предлага много повече от прости полета „задължителни срещу незадължителни“; можете да изразявате богати ограничения и трансформации директно върху вашите модели.

Тъй като схемата на OpenAPI е извлечена директно от вашите крайни точки и модели, FastAPI също така генерира интерактивна документация.От кутията получавате Swagger UI на /docs и ReDoc в /redoc, които са безценни при сътрудничество с frontend разработчици или интегратори от трети страни.

Под капака, FastAPI работи върху ASGI сървъри като UvicornТова позволява на приложението ви да обработва ефективно много едновременни връзки и активира функции като дълготрайни WebSocket връзки без допълнителни церемонии.

FastAPI също така е ясен относно заявките и отговоритеВсяка крайна точка е просто обикновена Python функция (sync или async), декорирана с @app.get, @app.post и приятели, получаващи данни за път/заявка/тяло и връщащи отговор, обикновено dict или Pydantic модел.

Асинхронност срещу синхронизация: как производителността се пресича със структурата

FastAPI е проектиран преди всичко като асинхронна рамка, но поддържа както асинхронни, така и синхронизиращи крайни точки.Разбирането на това как се държат вътрешно ще ви информира как проектирате услуги, избирате клиенти и структурирате модули, обработващи входно/изходни операции.

Когато декларирате async def маршрут, FastAPI го изпълнява директно в цикъла на събитиятаРамката приема, че всички дълго изпълняващи се операции вътре ще бъдат неблокиращи awaitables, като например драйвер за асинхронна база данни или HTTP клиент, изграден върху asyncio.

Ако случайно осъществите блокиращи повиквания (например time.sleep(), цикли с голямо натоварване на процесора или бавни библиотеки, които извършват мрежов входно/изходен трафик синхронно) вътре в тези асинхронни маршрути, вие ефективно ще замразите цикъла на събитияНикакви други заявки няма да бъдат обработени, докато тази операция не приключи, което обезсмисля целта на асинхронността.

Синхронизиращите маршрути се държат различно: FastAPI ги изпълнява в пул от нишкиБлокирането на работа в тези маршрути задържа само работна нишка, а не целия цикъл на събития, така че сървърът все още може да приема нови заявки. Ето как FastAPI остава гъвкав, когато трябва да разчитате на синхронни библиотеки.

Същите принципи важат и за зависимоститеПоддържат се както синхронизиращи, така и асинхронни зависимости, но синхронизиращите зависимости също се изпълняват в пул от нишки. За малки помощни програми, които не са I/O, често е по-добре да се маркират като асинхронни, за да се избегнат режийните разходи и ограниченията на нишките, когато това не е необходимо.

Работните натоварвания, ограничени от процесора, са отделна историяНезависимо дали ги изпълнявате синхронно или асинхронно вътре в процеса, GIL (Global Interpreter Lock) означава, че само една нишка изпълнява байткод на Python в даден момент. За задачи като обработка на тежки данни, транскодиране на изображения или машинно обучение, помислете за разтоварване на работата на работници в отделни процеси или външни опашки.

Валидиране и оформяне на данни с Pydantic

Pydantic е двигателят зад функциите за валидиране и сериализация на FastAPIТой предлага много повече от прости полета „задължителни срещу незадължителни“; можете да изразявате богати ограничения и трансформации директно върху вашите модели.

Типичните случаи на употреба включват валидиране на дължината на низове, числови диапазони, имейл формати или сложни вложени структуриМоделите могат също да разчитат на изброявания, регулярни изрази, персонализирани валидатори и много други инструменти, за да дезинфекцират входните данни, преди да достигнат до вашата бизнес логика.

Мощен модел е да дефинирате персонализиран базов модел за вашия проект.Чрез наследяване на всички схеми от един базов клас, можете да стандартизирате междусекторно поведение, като например формат за сериализация на дата и час, помощни методи, които връщат само JSON-безопасни стойности, или общи флагове за конфигурация.

Pydantic е чудесен за чиста проверка на данни, но не знае нищо за вашата база данни или външни услуги.Ако вашите правила зависят от заявка (като проверка дали съществува потребителски идентификатор или имейл адрес е уникален), често срещана най-добра практика е тези валидации да се преместят в зависимости, а не във валидатори на модели на Pydantic.

По този начин запазвате декларативните схеми и използвате повторно валидациите в множество крайни точки.Зависимостта може да извлече обект, да наложи правила за достъп и да инжектира резултата в маршрута, докато FastAPI кешира резултата си за всяка заявка, за да избегне дублиране на работа, когато една и съща зависимост се използва многократно.

Зависимостите като градивен елемент за чиста архитектура

Системата за инжектиране на зависимости на FastAPI не е просто синтактична захар за параметри; тя е основен архитектурен инструмент.Правилното използване на зависимости ви позволява да споделяте логика, да налагате инварианти и да поддържате маршрутите много малки и изразителни.

Често срещани примери включват доставчици на сесии за бази данни, зареждащи програми за конфигурация, помощни програми за удостоверяване и парсери за странициране.Вместо ръчно отваряне и затваряне на сесии или повтаряне на параметри за странициране навсякъде, вие ги декларирате веднъж като зависимости и ги използвате повторно.

Един фин, но важен съвет за дизайн е да се разделят зависимостите на малки, композируеми единици.Вместо един гигант get_current_user_with_all_checks функция, може да имате отделни зависимости за парсиране на JWT, зареждане на потребителя, проверка дали акаунтът е активен и проверка дали потребителят притежава даден ресурс.

Тъй като FastAPI кешира резултатите от зависимостите в рамките на една заявка, композирането им е евтино.Ако три различни зависимости използват повторно помощник от по-ниско ниво (например, парсиране на JWT твърдения), този помощник ще се изпълнява само веднъж на заявка, дори ако е посочен многократно.

При проектирането на маршрути, именуването на пътища може или да помогне, или да попречи на повторното използване на зависимости.Например, ако няколко крайни точки потвърдят, че profile_id съществува, използването на едно и също име последователно в параметрите на пътя улеснява включването на една зависимост, която разчита на profile_id, вместо да измислят много вариации, като например creator_id които носят същото значение.

Сигурност, удостоверяване и оторизация във вашата структура

Сигурността е една от областите, в които ясната структура се отплаща бързо.Смесването на логиката за удостоверяване директно в произволни маршрути затруднява одита на правилата за достъп и лесно води до случайно разкриване на данни.

Често срещан модел в оформленията, базирани на функции, е да има auth пакет със собствен рутер, схеми, сервизен слой и изключенияТози модул ще обработва регистрацията на потребители, процесите на влизане, издаването и проверката на токени и може да дефинира зависимости като get_current_user които други модули импортират.

В рамките на този пакет за удостоверяване можете да поддържате множество механизми за удостоверяване, като OAuth2 с парола и токени за носител, API ключове за повиквания от услуга към услуга или JWT-базирани токени за API без състояние. FastAPI fastapi.security Помощните програми ви помагат да опишете тези потоци и в OpenAPI.

Изключително важно е да се разграничи удостоверяването (кой е потребителят) от оторизацията (какво му е позволено да прави).Вашата структура трябва да показва ясно къде се намират проверките за разрешения: например в специален слой за услуги или правила, вместо разпръснати ad-hoc проверки. if изявления по всеки маршрут.

Винаги, когато работите с пароли, следвайте установените криптографски практикиХеширайте тайните с бавен, „солен“ алгоритъм като bcrypt или argon2 чрез реномирани библиотеки, избягвайте ръчно криптиране и третирайте съхранението на токени, CSRF защитата и сигурността на транспорта (HTTPS) като първокласни части от дизайна.

Ефективно тестване на FastAPI приложения

Структурата и тестването се подсилват взаимно: изчистеното оформление естествено води до по-тестируем код.С FastAPI можете да тествате на няколко нива, от чисти модулни тестове на услуги до пълни интеграционни тестове, достигащи HTTP слоя.

Единичните тестове трябва да се фокусират върху малки части без странични ефектиЧисти функции, валидатори на Pydantic, бизнес услуги, които работят с данни в паметта. Те обикновено са много бързи и са първата ви линия на защита срещу регресии.

За да упражнявате реални HTTP крайни точки, можете да използвате вградения тестов клиент, базиран на Starlette, или съвременни асинхронни клиенти, като например httpx.Идеята е да импортирате приложението си, да презапишете зависимостите, ако е необходимо (например, чрез инжектиране на тестова сесия в базата данни) и да изпращате заявки, без да стартирате външен сървър.

Ако работите с асинхронни драйвери за бази данни или други асинхронни интеграции, си струва да настроите асинхронен тестов клиент от самото начало.Смесването на стилове за синхронизирано и асинхронно тестване по-късно често води до объркващи проблеми с цикъла на събития, които са по-трудни за отстраняване на грешки, отколкото простото стандартизиране на един подход.

Използването на базата данни в тестовете също взаимодейства с вашата структураЧрез наличието на централно database.py модул, който дефинира фабриките за двигатели и сесии, става по-лесно да се разгръщат тестови бази данни, да се обгръщат тестове в транзакции или да се използват фиксиращи елементи, които отрязват таблиците между изпълненията.

От локално развитие до внедряване в производство

Приложенията на FastAPI са лесни за изпълнение локално, но изискват малко повече планиране в производствения процес.Структурата на вашия проект трябва да показва ясно как е създадено приложението, откъде идва конфигурацията и как са свързани регистрирането и проверките за състояние.

За разработка повечето екипи използват Uvicorn с автоматично презареждане., обикновено чрез команда като uvicorn app.main:app --reload или, в по-нови конфигурации, fastapi devТова осигурява бързи цикли на обратна връзка и е перфектно по време на итерация.

В производството обикновено е необходима по-стабилна настройка.Работниците на Uvicorn или Hypercorn, управлявани от супервайзор на процеси или WSGI/ASGI обвивка като Gunicorn, често зад обратен прокси (NGINX или управляван балансьор на натоварването). Целта е да се контролира броят на работниците, времето за изчакване и плавните рестартирания, информирани от съвременни DevOps практики.

Конфигурацията трябва да се управлява от променливи на средата, а не от твърдо кодирани стойностиУправлението на настройките на Pydantic или подобни инструменти могат да ви помогнат да декларирате класове с типизирани настройки и да ги заредите при стартиране, централизирайки всички специфични за средата копчета на едно място.

Преди да обявите приложението си за готово за производство, проверете няколко основни неща: структурирано регистриране, основни показатели, крайни точки за състояние на сонди за активност и готовност, разумни ограничения за размера на тялото и ясна политика за предоставяне на документация само в непублични среди, ако вашият API не е предназначен за обща употреба.

Именуване, дизайн на база данни и миграции

Начинът, по който именувате нещата във вашите модели и файлове със схеми, също е част от структурата на вашия проект.Непоследователното именуване е един от най-бързите начини да объркате разработчиците, работещи върху кодова база, която не са създали.

Една проста и ефективна конвенция е да се използва lower_case_snake имена за таблици и колони, предпочитайте имена на таблици в единствено число (например post, post_like, user_playlist) и групирайте свързани таблици с общ префикс, като например payment_ or post_.

За темпорални полета, суфикси като _at за дати и часове _date за обикновени дати, дръжте нещата ясниСтриктното спазване тук предотвратява играта на догадки от типа „това времева маркировка ли е или дата?“ при четене на схеми или сурови заявки.

Миграциите заслужават специално внимание; те трябва да бъдат детерминистични, обратими и описателни — помислете за следното практики за мигриране на бази данниМного екипи възприемат модел за имена на файлове за миграция, като например YYYY-MM-DD_slug.py, което улеснява проследяването на историята и разбирането на промените, без да е необходимо да се чете пълната разлика.

За сложни отчети или вложени отговори, използвайте базата данни, вместо да я преработвате в Python.Съвременните SQL енджини могат да извършват съединения, агрегации и изграждане на JSON много по-бързо от CPython, а връщането на предварително оформени структури към FastAPI често опростява вашите модели на отговори.

Инструменти, форматиране и екипни конвенции

Добре структурираният проект е по-лесен за поддържане на чистота, когато използвате инструменти за прилагане на стилови правила.Форматерите на код, линтерите и куките за предварително записване ви помагат да се съсредоточите върху бизнес логиката, вместо да спорите за празните пространства при прегледите на кода.

Напоследък инструменти като Ruff станаха популярни, защото комбинират множество роли в една.Вместо да жонглирате с отделни инструменти за форматиране, сортиране на импортиране и линтинг, можете да стартирате един бърз инструмент, който налага стотици правила в цялата кодова база.

Изпълнението на тези инструменти чрез прост скрипт или куки за предварително записване поддържа ниска бариераНе всеки екип се нуждае от сложна настройка на hook-ове, но наличието на поне една команда, която стандартизира оформлението на кода, е лесна победа.

Накрая, помислете за документиране на вашите вътрешни конвенции в кратко „инженерно ръководство“ който препраща гъвкави методи за разработване на софтуерОпишете как трябва да се именуват модулите, кога да се създава нов домейн пакет, как да се структурират тестовете и кои модели за сигурност са задължителни. Това предотвратява знанията да се съхраняват само в главите на старши разработчици.

Проектирането на структурата на FastAPI проект всъщност е свързано с това да направи бъдещата работа предвидима и скучна.Когато всяка нова крайна точка, модел или услуга има очевидно местоположение, разработчиците могат да действат бързо без изненади, сигурността е по-лесна за одитиране и приложението има много по-голям шанс да оцелее при растеж в реалния свят, без да се срине под собствената си тежест.

Свързана статия:
Решено: бърз синтаксис на шаблон на API
Подобни публикации: