{"id":21457818,"url":"https://github.com/sumaro2101/basefastapi","last_synced_at":"2025-04-22T13:38:58.292Z","repository":{"id":263045554,"uuid":"889175308","full_name":"sumaro2101/BaseFastAPI","owner":"sumaro2101","description":"Base Template FastAPI for quick start any project.","archived":false,"fork":false,"pushed_at":"2024-12-21T11:11:13.000Z","size":122,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-21T11:29:14.772Z","etag":null,"topics":["alembic","api","asychronous","caddy","celery","docker","docker-compose","fastapi","git","grafana","logging","poetry","postgresql","prometheus","rebbitmq","sqlalchemy"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sumaro2101.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-15T18:57:19.000Z","updated_at":"2024-12-21T11:08:54.000Z","dependencies_parsed_at":"2024-11-15T20:19:07.745Z","dependency_job_id":"e4cefda8-99d1-4a6e-badd-819f0b2e0734","html_url":"https://github.com/sumaro2101/BaseFastAPI","commit_stats":null,"previous_names":["sumaro2101/basefastapi"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumaro2101%2FBaseFastAPI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumaro2101%2FBaseFastAPI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumaro2101%2FBaseFastAPI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sumaro2101%2FBaseFastAPI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sumaro2101","download_url":"https://codeload.github.com/sumaro2101/BaseFastAPI/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235289081,"owners_count":18965876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alembic","api","asychronous","caddy","celery","docker","docker-compose","fastapi","git","grafana","logging","poetry","postgresql","prometheus","rebbitmq","sqlalchemy"],"created_at":"2024-11-23T06:07:13.753Z","updated_at":"2025-01-23T13:29:47.079Z","avatar_url":"https://github.com/sumaro2101.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Title\n\nДанный шаблон был разработан для одной цели - облегчения и повышения качества\nвыполненых тестовых заданий в рамках **FastAPI**.\n\n# Quick start\n\nДля тех кто уже знаком с реализацией и всеми деталями - могут приступить к установке.\n\n## GIT\n\nДля безопасного выполнения копирования из GitHub Необходимо сделать следующее:\n\n- Клонировать Git репозиторий\n\n```bash\ngit clone https://github.com/sumaro2101/BaseFastAPI your_name_dir\n```\n\nГде \u003chttps://github.com/sumaro2101/BaseFastAPI\u003e - адресс репозитория,\n`your_name_dir` - имя папки для клонирования\n\n- Удалить .git из клонированного репозитория\n\n```bash\nrm -r .git\n```\n\nили если отказывает в доступе можете - переместить\n\n```bash\nmv .git ../git\n```\n\n- Инициализировать свой `Git`\n\n```bash\ngit init\n```\n\n- Сделать свой коммит\n\n```bash\ngit add .\ngit commit -m 'base commit'\n```\n\n- Привязать текущий Git к вашему удаленному репозиторию\n\n```bash\ngit remove add origin some_url_or_ssh_repo\n```\n\n- Отправить на удаленный репозиторий текущий репозиторий\n\n```bash\ngit push -u origin main\n```\n\n## Enviroments\n\nНеобходимо заполнить **.env.sample** и в последствии перемеиновать его в **.env**\n\n```python\n# .env.sample\nPOSTGRES_PASSWORD=password # Пароль от базы данных (Настройка)\nDB_PASSWORD=password # Пароль от базы данных (Использование)\nTEST_POSTGRES_PASSWORD=password # Пароль от тестовой базы данный (Настройка)\nTEST_DB_PASSWORD=password # Пароль от тестовой базы данных (Использование)\n```\n\n## Docker\n\nШаблон находится под системой управления и контеризации - **Docker**.\nЕсли у вас нет Docker - вы можете установить его с официального сайта: [Docker](https://www.docker.com/get-started/)\n\n- Вам необходимо сделать \"Билд\"\n\n```bash\ndocker compose build\n```\n\n- Вам необходимо запустить окружение\n\n```bash\ndocker compose up\n```\n\n- После успешного запуска приложение будет доступно по адрессу: \u003chttp://localhost:8080\u003e\n- Grafana: \u003chttp://localhost:3000\u003e\n- Flower: \u003chttp://localhost:5555\u003e\n\n# View\n\nОбзор и детали данного шаблона\n\n## Users\n\nВ данном шаблоне реализован CRUD для пользователя с помощью библиотеки\n[fastapi-users](https://fastapi-users.github.io/fastapi-users/latest/)\n\n### End-points\n\n`USERS`\n\n- \u003chttp://localhost:8080/api/v1/users/me\u003e GET\nПолучение текущего пользователя\n- \u003chttp://localhost:8080/api/v1/users/me\u003e PATCH\nИзменение текущего пользователя\n- \u003chttp://localhost:8080/api/v1/users/{id}\u003e GET\nПолучение пользователя по ID Необходимо иметь права доступа уровня `admin`\n- \u003chttp://localhost:8080/api/v1/users/{id}\u003e PATCH\nИзменение пользоватея по ID Необходимо иметь права доступа уровня `admin`\n- \u003chttp://localhost:8080/api/v1/users/{id}\u003e DELETE\nУдаление пользоватея по ID Необходимо иметь права доступа уровня `admin`\n\n`AUTH`\n\n- \u003chttp://localhost:8080/api/v1/auth/jwt/login\u003e POST\nАутентификация в систему с последующим получением JWT для авторизации\n- \u003chttp://localhost:8080/api/v1/auth/jwt/logout\u003e POST\nВызод из системы\n- \u003chttp://localhost:8080/api/v1/auth/register\u003e POST\nРегистрация нового пользователя\n- \u003chttp://localhost:8080/api/v1/auth/request-verify-token\u003e POST\nПолучение токена для верификации. `ВАЖНО` Читайте ниже, есть нюанс.\n- \u003chttp://localhost:8080/api/v1/auth/verify\u003e POST\nВерификация пользователя по токену\n- \u003chttp://localhost:8080/api/v1/auth/forgot-password\u003e POST\nПолучение токена для изменения пароль. `ВАЖНО` Читайте ниже, есть нюанс.\n- \u003chttp://localhost:8080/api/v1/auth/reset-password\u003e POST\nИзменения пароля посредством токена\n\n`ВАЖНО`\n\n- \u003chttp://localhost:8080/api/v1/auth/forgot-password\u003e POST\nДолжен осуществлять логику отправки токена по эмеилу либо другим способом.\nВ данный момент отправка осуществляется через `консоль`.\nДля деталей смотрите миксин `api_v1/users/mixins/ActionUserManagerMixin`\n- \u003chttp://localhost:8080/api/v1/auth/forgot-password\u003e POST\nДолжен осуществлять логику отправки токена по эмеилу либо другим способом.\nВ данный момент отправка осуществляется через `консоль`.\nДля деталей смотрите миксин `api_v1/users/mixins/ActionUserManagerMixin`\n\n### UserManager\n\nUserManager Это специальная обвертка для `SQLAlchemyUserDatabase` который в свою\nочередь вмещает в себя класс модели `User` и сессию `AsyncSession`\nСмотрите класс `api_v1/users/user_manager/UserManager`\n\n### Transport\n\nВ fastapi-users есть 2 вида транспорта:\n\n- [Bearer](https://fastapi-users.github.io/fastapi-users/latest/configuration/authentication/transports/bearer/)\n- [Cookie](https://fastapi-users.github.io/fastapi-users/latest/configuration/authentication/transports/cookie/)\n\nВ шаблоне реализован Bearer способ:\n\n```python\nfrom fastapi_users.authentication import BearerTransport\n\nfrom config import settings\n\n\nbearer_transport = BearerTransport(settings.CURRENT_ORIGIN +\n                                   settings.API_PREFIX +\n                                   settings.JWT.JWT_PATH +\n                                   '/login')\n```\n\n### Strategy\n\nВ fastapi-users есть 3 вида стратегии:\n\n- [Database](https://fastapi-users.github.io/fastapi-users/latest/configuration/authentication/strategies/database/)\n- [JWT](https://fastapi-users.github.io/fastapi-users/latest/configuration/authentication/strategies/jwt/)\n- [Redis](https://fastapi-users.github.io/fastapi-users/latest/configuration/authentication/strategies/redis/)\n\nВ Шаблоне реализован JWT способ:\n\n```python\nfrom fastapi_users.authentication import JWTStrategy\n\nfrom config import settings\n\n\ndef get_jwt_strategy() -\u003e JWTStrategy:\n    return JWTStrategy(\n        secret=settings.JWT.SECRET,\n        lifetime_seconds=settings.JWT.RESET_LIFESPAN_TOKEN_SECONDS,\n        )\n```\n\n### Backend\n\nauth_backend собирает `Transport` и `Strategy` воединно в `AuthenticationBackend`\nЭтот класс необходим будет для:\n\n- `Authenticator`\n- `FastAPIUsers`\n\n```python\nfrom fastapi_users.authentication import AuthenticationBackend\n\nfrom config import settings\n\n\nauth_backend = AuthenticationBackend(\n    name=settings.JWT.NAME,\n    transport=bearer_transport,\n    get_strategy=get_jwt_strategy,\n)\n```\n\n### Authenticator\n\nAuthenticator необходим для `Callback[Depenpency]` пользователей,\nприменяется для вытаскивания текущего пользователя.\n\n```python\nfrom fastapi import Depends\nfrom fastapi_users.authentication import Authenticator\n\nfrom config.models import User\n\n\nauthenticator = Authenticator(\n    (auth_backend,),\n    get_user_manager,\n)\n\nactive_user = authenticator.current_user(\n    active=True,\n    verified=True,\n)\n\nasync def get_user(user: User = Depends(active_user)) -\u003e User:\n    return user\n```\n\n### FastAPIUsers\n\nFastAPIUsers применяется в итоговом выводе End-points в API\n\n```python\nfrom fastapi import APIRouter\nfrom fastapi_users import FastAPIUsers\n\nfrom api_v1.auth.schemas import UserRead, UserUpdate\n\n\nfastapi_users = FastAPIUsers[User, int](\n    get_user_manager,\n    (auth_backend,)\n)\n\nrouter = APIRouter()\n\nrouter.include_router(fastapi_users.get_users_router(UserRead, UserUpdate),\n                      tags=['Users'],\n                      prefix='/users',\n                      )\n```\n\nПо итогу будет добавлены новые End-points в API\n\n### Permissions\n\nС помощью Authenticator возможно осуществлять права доступа к End-points\n`api_v1/auth/permissions.py` содержит несколько `Callback` функции для permissions\nПо желанию вы можете подолнять их.\n\n```python\nfrom fastapi import APIRouter\n\nfrom api_v1.auth import active_user\n\n\nrouter = APIRouter()\n\n\n@router.get(path='/get-user')\nasync def get_user(user: User = Depends(active_user)) -\u003e User:\n    return user\n```\n\n## Найболее используемые\n\nНайболее используемые конструкции с которыми приходится часто взаимодействовать.\n\n### Registration Routers\n\n- В каждом приложений необходимо инициализировать router\n\n```python\n# api/users/views.py\nfrom fastapi import APIRouter\n\n\nrouter = APIRouter(\n    prefix='/users',\n    tags=['Users'],\n    )\n```\n\n- Затем зарегистрировать роутер\n\n```python\n# api_v1/routers.py\nfrom api_v1.users.views import router as users\nfrom config import settings\n\n\n# В этой функции нужно по порядку регистрировать routers\ndef register_routers(app: FastAPI) -\u003e None:\n    app.include_router(\n        router=users,\n        prefix=settings.API_PREFIX,\n    )\n```\n\nПосле регистрации данные маршруты будут доступны.\n\n### Registration Logs\n\n- Логи захватывают все исключения возникшие в системе\nи с помошью диспечиризации распределяется по нужным **file.log**\n\n```python\n# app_includes/logs_errors.py\nfrom fastapi import FastAPI\nfrom fastapi.responses import JSONResponse\n\nfrom api_v1.exeptions import ValidationError\n\n\n# В данной функции регистрируются все исключения для захватывания Логами\ndef register_errors(app: FastAPI) -\u003e None:\n    @app.exception_handler(ValidationError)\n    async def validation_error_handler(\n        request: Request,\n        exc: ValidationError,\n    ):\n        logger.opt(exception=True).warning(exc)\n        response = dict(\n            status=False,\n            error_code=exc.status_code,\n            message=exc.detail,\n        )\n        return JSONResponse(response)\n```\n\n- Если вы пишете пользовательское исключение например:\n\n```python\nfrom starlette.exceptions import HTTPException\n\n\nclass ValidationError(HTTPException):\n\npass\n```\n\nТо вам нужно его зарегистрировать как было показанно выше,\nиначе logs не смогут выявить данное исключение и данные будут утеряны.\n\n### Registration Middlaware\n\n- Для регистрации Middlaware вам нужно добавить его в функцию\n\n```python\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi import FastAPI\n\nfrom config import settings\n\n\n# Данная функция регистрирует все middleware\ndef register_middlewares(app: FastAPI) -\u003e None:\n    app.add_middleware(\n        CORSMiddleware,\n        allow_origins=[\n            settings.CURRENT_ORIGIN,\n        ],\n        allow_credentials=True,\n        allow_methods=['*'],\n        allow_headers=['*'],\n    )\n```\n\n- При появлении новых middleware добавляйте их по порядку в эту функцию\n\n### DAO\n\nDAO необходим для CRUD manager любой модели.\n`config.dao.base_dao.BaseDAO`\n\nДля опеределения DAO вашей модели нужно наследовать `BaseDAO`, а Затем\nпереопределить поле класса `model`\n\n```python\nfrom config.dao import BaseDAO\nfrom config.models import Product\n\n\nclass ProductDAO(BaseDAO):\n    model = Product\n```\n\n### Celery\n\n- Для регистрации task вам нужно создать файл с именем **tasks.py** в вашем приложении:\n\n```python\n# api_v1/users/tasks.py\nfrom config import celery_app\nimport asyncio\n\n\n@celery_app.task\nasync def time_sleep_task():\n    \"\"\"\n    Тестовая задача для Celery\n    \"\"\"\n    await asyncio.sleep(2.0)\n    return 'Task is done'\n```\n\n- Затем добавить этот файл в список пакетов Celery\n\n```python\n# confin.celery.connection.py\n\napp = Celery(__name__)\napp.conf.broker_url = settings.rabbit.broker_url\n# Регистрация до окружения где находится tasks.py\napp.autodiscover_tasks(packages=['api_v1.users'])\n```\n\n- После этих действий ваша task будет зарегистрирована\n\n### Test\n\n- Для тестирования у вас есть тестовая база данных, а так же\nуже инициализированный отдельный клиент.\nCпособ реализации в **api_v1/tests/conftest.py**\n- Что бы написать тестовую функцию которой нужен доступ к API,\nвам нужно использовать fixture - client.\n\n\u003e [!NOTE]\n\u003e Для асинхронных тестов используйте **@pytest.mark.asyncio**\n\n```python\n# api_v1.tests.test_users.py\nimport pytest\n\n\n@pytest.mark.asyncio\nasync def test_get_user_error(client: AsyncClient):\n    response = await client.get(\n        '/users/get',\n    )\n    assert response.status_code == 400\n```\n\n- Для запуска используйте команду\n\n```bash\npytest\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumaro2101%2Fbasefastapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsumaro2101%2Fbasefastapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsumaro2101%2Fbasefastapi/lists"}