{"id":13594177,"url":"https://github.com/teamhide/fastapi-boilerplate","last_synced_at":"2025-05-16T02:08:12.286Z","repository":{"id":37642508,"uuid":"248507413","full_name":"teamhide/fastapi-boilerplate","owner":"teamhide","description":"FastAPI boilerplate for real world production","archived":false,"fork":false,"pushed_at":"2024-05-26T12:03:46.000Z","size":504,"stargazers_count":1276,"open_issues_count":15,"forks_count":194,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-08T12:12:10.567Z","etag":null,"topics":["api","asyncio","boilerplate","fastapi","fastapi-boilerplate","fastapi-template","python","sqlalchemy","sqlalchemy-async"],"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/teamhide.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":"2020-03-19T13:15:06.000Z","updated_at":"2025-04-08T11:48:29.000Z","dependencies_parsed_at":"2024-01-14T04:34:38.812Z","dependency_job_id":"1e3affe7-50b1-47f9-a2f9-323354c4b8b3","html_url":"https://github.com/teamhide/fastapi-boilerplate","commit_stats":{"total_commits":128,"total_committers":3,"mean_commits":"42.666666666666664","dds":0.046875,"last_synced_commit":"ca3bb3fa5686cb031d6cd99d45b34fd7d2b12494"},"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teamhide%2Ffastapi-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teamhide%2Ffastapi-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teamhide%2Ffastapi-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teamhide%2Ffastapi-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teamhide","download_url":"https://codeload.github.com/teamhide/fastapi-boilerplate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453655,"owners_count":22073617,"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":["api","asyncio","boilerplate","fastapi","fastapi-boilerplate","fastapi-template","python","sqlalchemy","sqlalchemy-async"],"created_at":"2024-08-01T16:01:29.774Z","updated_at":"2025-05-16T02:08:12.269Z","avatar_url":"https://github.com/teamhide.png","language":"Python","readme":"# FastAPI Boilerplate\n\n# Features\n- Async SQLAlchemy session\n- Custom user class\n- Dependencies for specific permissions\n- Celery\n- Dockerize(Hot reload)\n- Event dispatcher\n- Cache\n\n## Run\n\n### Launch docker\n```shell\n\u003e docker-compose -f docker/docker-compose.yml up\n```\n\n### Install dependency\n```shell\n\u003e poetry shell\n\u003e poetry install\n```\n\n### Apply alembic revision\n```shell\n\u003e alembic upgrade head\n```\n\n### Run server\n```shell\n\u003e python3 main.py --env local|dev|prod --debug\n```\n\n### Run test codes\n```shell\n\u003e make test\n```\n\n### Make coverage report\n```shell\n\u003e make cov\n```\n\n### Formatting\n\n```shell\n\u003e pre-commit\n```\n\n## SQLAlchemy for asyncio context\n\n```python\nfrom core.db import Transactional, session\n\n\n@Transactional()\nasync def create_user(self):\n    session.add(User(email=\"padocon@naver.com\"))\n```\n\nDo not use explicit `commit()`. `Transactional` class automatically do.\n\n### Query with asyncio.gather()\nWhen executing queries concurrently through `asyncio.gather()`, you must use the `session_factory` context manager rather than the globally used session.\n\n```python\nfrom core.db import session_factory\n\n\nasync def get_by_id(self, *, user_id) -\u003e User:\n    stmt = select(User)\n    async with session_factory() as read_session:\n        return await read_session.execute(query).scalars().first()\n\n\nasync def main() -\u003e None:\n    user_1, user_2 = await asyncio.gather(\n        get_by_id(user_id=1),\n        get_by_id(user_id=2),\n    )\n```\nIf you do not use a database connection like `session.add()`, it is recommended to use a globally provided session.\n\n### Multiple databases\n\nGo to `core/config.py` and edit `WRITER_DB_URL` and `READER_DB_URL` in the config class.\n\n\nIf you need additional logic to use the database, refer to the `get_bind()` method of `RoutingClass`.\n\n## Custom user for authentication\n\n```python\nfrom fastapi import Request\n\n\n@home_router.get(\"/\")\ndef home(request: Request):\n    return request.user.id\n```\n\n**Note. you have to pass jwt token via header like `Authorization: Bearer 1234`**\n\nCustom user class automatically decodes header token and store user information into `request.user`\n\nIf you want to modify custom user class, you have to update below files.\n\n1. `core/fastapi/schemas/current_user.py`\n2. `core/fastapi/middlewares/authentication.py`\n\n### CurrentUser\n\n```python\nclass CurrentUser(BaseModel):\n    id: int = Field(None, description=\"ID\")\n```\n\nSimply add more fields based on your needs.\n\n### AuthBackend\n\n```python\ncurrent_user = CurrentUser()\n```\n\nAfter line 18, assign values that you added on `CurrentUser`.\n\n## Top-level dependency\n\n**Note. Available from version 0.62 or higher.**\n\nSet a callable function when initialize FastAPI() app through `dependencies` argument.\n\nRefer `Logging` class inside of `core/fastapi/dependencies/logging.py`\n\n## Dependencies for specific permissions\n\nPermissions `IsAdmin`, `IsAuthenticated`, `AllowAll` have already been implemented.\n\n```python\nfrom core.fastapi.dependencies import (\n    PermissionDependency,\n    IsAdmin,\n)\n\n\nuser_router = APIRouter()\n\n\n@user_router.get(\n    \"\",\n    response_model=List[GetUserListResponseSchema],\n    response_model_exclude={\"id\"},\n    responses={\"400\": {\"model\": ExceptionResponseSchema}},\n    dependencies=[Depends(PermissionDependency([IsAdmin]))],  # HERE\n)\nasync def get_user_list(\n    limit: int = Query(10, description=\"Limit\"),\n    prev: int = Query(None, description=\"Prev ID\"),\n):\n    pass\n```\nInsert permission through `dependencies` argument.\n\nIf you want to make your own permission, inherit `BasePermission` and implement `has_permission()` function.\n\n**Note. In order to use swagger's authorize function, you must put `PermissionDependency` as an argument of `dependencies`.**\n\n## Event dispatcher\n\nRefer the README of https://github.com/teamhide/fastapi-event\n\n## Cache\n\n### Caching by prefix\n```python\nfrom core.helpers.cache import Cache\n\n\n@Cache.cached(prefix=\"get_user\", ttl=60)\nasync def get_user():\n    ...\n```\n\n### Caching by tag\n```python\nfrom core.helpers.cache import Cache, CacheTag\n\n\n@Cache.cached(tag=CacheTag.GET_USER_LIST, ttl=60)\nasync def get_user():\n    ...\n```\n\nUse the `Cache` decorator to cache the return value of a function.\n\nDepending on the argument of the function, caching is stored with a different value through internal processing.\n\n### Custom Key builder\n\n```python\nfrom core.helpers.cache.base import BaseKeyMaker\n\n\nclass CustomKeyMaker(BaseKeyMaker):\n    async def make(self, function: Callable, prefix: str) -\u003e str:\n        ...\n```\n\nIf you want to create a custom key, inherit the BaseKeyMaker class and implement the make() method.\n\n### Custom Backend\n\n```python\nfrom core.helpers.cache.base import BaseBackend\n\n\nclass RedisBackend(BaseBackend):\n    async def get(self, key: str) -\u003e Any:\n        ...\n\n    async def set(self, response: Any, key: str, ttl: int = 60) -\u003e None:\n        ...\n\n    async def delete_startswith(self, value: str) -\u003e None:\n        ...\n```\n\nIf you want to create a custom key, inherit the BaseBackend class and implement the `get()`, `set()`, `delete_startswith()` method.\n\nPass your custom backend or keymaker as an argument to init. (`/app/server.py`)\n\n```python\ndef init_cache() -\u003e None:\n    Cache.init(backend=RedisBackend(), key_maker=CustomKeyMaker())\n```\n\n### Remove all cache by prefix/tag\n\n```python\nfrom core.helpers.cache import Cache, CacheTag\n\n\nawait Cache.remove_by_prefix(prefix=\"get_user_list\")\nawait Cache.remove_by_tag(tag=CacheTag.GET_USER_LIST)\n```\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteamhide%2Ffastapi-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteamhide%2Ffastapi-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteamhide%2Ffastapi-boilerplate/lists"}