{"id":20973685,"url":"https://github.com/grillazz/fastapi-sqlalchemy-asyncpg","last_synced_at":"2025-04-08T09:06:06.666Z","repository":{"id":38334360,"uuid":"351697323","full_name":"grillazz/fastapi-sqlalchemy-asyncpg","owner":"grillazz","description":"Integration of FastAPI framework supported by Pydantic with SQLAlchemy ORM and PostgreSQL on asyncpg driver","archived":false,"fork":false,"pushed_at":"2025-03-08T19:53:35.000Z","size":8140,"stargazers_count":451,"open_issues_count":9,"forks_count":60,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-01T07:49:03.370Z","etag":null,"topics":["asyncio","asyncpg","docker","fastapi","fastapi-sqlalchemy","granian","postgresql","pydantic","python","python3","sqlalchemy","uvicorn"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grillazz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-03-26T07:26:51.000Z","updated_at":"2025-04-01T00:06:54.000Z","dependencies_parsed_at":"2023-02-19T00:30:24.673Z","dependency_job_id":"b13219ef-a94f-4c45-905e-f4beb495c475","html_url":"https://github.com/grillazz/fastapi-sqlalchemy-asyncpg","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grillazz%2Ffastapi-sqlalchemy-asyncpg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grillazz%2Ffastapi-sqlalchemy-asyncpg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grillazz%2Ffastapi-sqlalchemy-asyncpg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grillazz%2Ffastapi-sqlalchemy-asyncpg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grillazz","download_url":"https://codeload.github.com/grillazz/fastapi-sqlalchemy-asyncpg/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247809963,"owners_count":20999816,"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":["asyncio","asyncpg","docker","fastapi","fastapi-sqlalchemy","granian","postgresql","pydantic","python","python3","sqlalchemy","uvicorn"],"created_at":"2024-11-19T04:20:50.746Z","updated_at":"2025-04-08T09:06:06.618Z","avatar_url":"https://github.com/grillazz.png","language":"Python","readme":"# fastapi-sqlalchemy-asyncpg\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n[![LinkedIn][linkedin-shield]][linkedin-url]\n\n![fastapi-sqlalchemy-asyncpg](/static/fsap_1.jpg)\n\n\u003ca name=\"readme-top\"\u003e\u003c/a\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eTable of Contents\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#built-with\"\u003eBuilt With\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#make-will-help-you\"\u003eMake will help you\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#how-to-feed-database\"\u003eHow to feed database\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#rainbow-logs-with-rich\"\u003eRainbow logs with rich\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#setup-user-auth\"\u003eSetup user auth\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#setup-local-env-with-uv\"\u003eSetup local development with uv\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#import-xlsx-files-with-polars-and-calamine\"\u003eImport xlsx files with polars and calamine\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#worker-aware-async-scheduler\"\u003eSchedule jobs\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#smtp-setup\"\u003eEmail Configuration\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#uv-knowledge-and-inspirations\"\u003eUV knowledge and inspirations\u003c/a\u003e\u003c/li\u003e \n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#acknowledgments\"\u003eAcknowledgments\u003c/a\u003e\u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/details\u003e\n\n[//]: # (TODO: Usage,Roadmap, Contributing, License, Contact)\n\n    \n## About The Project\n\nThis example demonstrates the seamless integration of [FastAPI](https://fastapi.tiangolo.com/), a modern, high-performance web framework,\nwith [Pydantic 2.0](https://github.com/pydantic/pydantic), a robust and powerful data validation library.\nThe integration is further enhanced by the use of [SQLAlchemy ORM](https://www.sqlalchemy.org/), a popular and feature-rich Object-Relational Mapping tool,\nand [PostgreSQL17](https://www.postgresql.org/docs/17/release.html) relational database.\n\nThe entire stack is connected using the [asyncpg](https://github.com/MagicStack/asyncpg) Database Client Library,\nwhich provides a robust and efficient way to interact with PostgreSQL databases in Python,\nleveraging the power of asyncio and event loops.\n\nNotably, this example showcases the latest and greatest versions of SQLAlchemy and psycopg,\nwhich are renowned for their robustness, power, and speed. The inclusion of FastAPI adds a modern, fast, and high-performance web framework to the mix\nallowing for the rapid development of APIs with Python 3.8+.\n\nFastAPI has received significant recognition in the industry, including a review on thoughtworks Technology Radar in April 2021,\nwhere it was classified as a Trial technology, with comments praising its performance, ease of use,\nand features such as API documentation using OpenAPI. Additionally, FastAPI was recognized in the Python Developers Survey 2023 Results,\nconducted by the Python Software Foundation and JetBrains, where it was reported that 1 in 4 Python developers use FastAPI,\nwith a 4 percentage point increase from the previous year.\n\n\n### Built With\n[![FastAPI][fastapi.tiangolo.com]][fastapi-url]\n[![Pydantic][pydantic.com]][pydantic-url]\n[![SQLAlchemy][sqlalchemy.org]][sqlalchemy-url]\n[![Uvicorn][uvicorn.org]][uvicorn-url]\n[![pytest][pytest.org]][pytest-url]\n[![asyncpg][asyncpg.github.io]][asyncpg-url]\n[![alembic][alembic.sqlalchemy.org]][alembic-url]\n[![rich][rich.readthedocs.io]][rich-url]\n\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n## Getting Started\n\n### Make will help you\nTo build , run and test and more ... use magic of make help to play with this project.\n```shell\n1. make docker-build\n2. make docker-up \u003e alternatively \u003e make docker-up-granian\n3. make docker-apply-db-migrations\n4. make docker-feed-database\n```\n\n### Adjust make with just\n[//]: # (TODO: switch form make to just)\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### How to feed database\n\nIt took me a while to find nice data set. Hope works of Shakespeare as example will be able to cover \nfirst part with read only declarative base configuration and all type of funny selects :)\nData set is coming form https://github.com/catherinedevlin/opensourceshakespeare\nNext models were generated with https://github.com/agronholm/sqlacodegen\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Rainbow logs with rich :rainbow:\n\nTo enhance the developer experience when viewing logs with extensive information from multiple emitters \n(which are particularly useful during development), this project uses the [rich](https://github.com/Textualize/rich) library.\nEvent with the superpowers of [rich](https://github.com/Textualize/rich), reading logs can be challenging.\nThe [rich](https://github.com/Textualize/rich) library is highly beneficial, but integrating it properly as a logger object\nand maintaining it as a singleton took some effort.\n\nTo address the following needs:\n- Difficulty in finding specific information in logs.\n- Avoiding the complexity of setting up an ELK stack for log management.\n- Speeding up the debugging process.\n\nhe following steps were taken to integrate [rich](https://github.com/Textualize/rich) into the project:\n1. Configure emitters using the [logging-uvicorn.json](https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/blob/main/logging-uvicorn.json)\n   or use [logging-granian.json](https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/blob/main/logging-granian.json) for granian\n2. Eliminate duplicates, such as SQLAlchemy echo, by using separate handlers.\n3. Maintain the logger as a singleton to prevent multiple instances.\n4. Add the --log-config ./logging-uvicorn.json parameter to Uvicorn or --log-config ./logging-granian.json to Granian.\n\n![sample-logs-with-rich](/static/logz.png)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Setup User Auth\n\nSetup user authentication with JWT and Redis as token storage.\n\n### Setup local env with uv\n```shell\nuv sync\nsource .venv/bin/activate\n```\n\n### Import xlsx files with polars and calamine\nPower of Polars Library in data manipulation and analysis.\nIt uses the polars library to read the Excel data into a DataFrame by passing the bytes to the `pl.read_excel()` function -\nhttps://docs.pola.rs/py-polars/html/reference/api/polars.read_excel.html\nIn `pl.read_excel()` “calamine” engine can be used for reading all major types of Excel Workbook (.xlsx, .xlsb, .xls) and is dramatically faster than the other options, using the fastexcel module to bind calamine.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Worker aware async scheduler\nThe project uses the APScheduler library to schedule tasks in the background.\nThe APScheduler library is a powerful and flexible in-process task scheduler with Cron-like capabilities.\nIt allows you to schedule jobs to run at specific times or intervals, and it supports multiple job stores, triggers, and executors.\nThe library is designed to be easy to use and highly configurable, making it suitable for a wide range of use cases.\nIt was added to project in version 4.0.0a5 with Redis as event broker and SQLAlchemy as data store.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### SMTP setup\nThe project uses the `smtplib` library to send emails.\nThe `smtplib` library is a built-in Python library that provides a simple interface for sending emails using the Simple Mail Transfer Protocol (SMTP).\nIt allows you to connect to an SMTP server, send an email message, and disconnect from the server.\nThe library is easy to use and provides a flexible and powerful way to send emails from your Python applications.\n\nSMTPEmailService provides a reusable interface to send emails via an SMTP server.\nThis service supports plaintext and HTML emails, and also allows sending template-based emails using the Jinja2 template engine.\nIt is implemented as a singleton to ensure that only one SMTP connection is maintained\nthroughout the application lifecycle, optimizing resource usage.\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### UV knowledge and inspirations\n- https://docs.astral.sh/uv/\n- https://hynek.me/articles/docker-uv/\n- https://thedataquarry.com/posts/towards-a-unified-python-toolchain/\n- https://www.youtube.com/watch?v=ifj-izwXKRA\u0026t=760s \u003e UV and Ruff: Next-gen Python Tooling\n- https://www.youtube.com/watch?v=8UuW8o4bHbw\u0026t=1s \u003e uv IS the Future of Python Packaging! 🐍📦\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n## Acknowledgments\nUse this space to list resources you find helpful and would like to give credit to.\nI've included a few of my favorites to kick things off!\n\n* [Open Source Shakespeare Dataset](https://github.com/catherinedevlin/opensourceshakespeare)\n* [SQL Code Generator](https://github.com/agronholm/sqlacodegen)\n* [Passlib - password hashing library for Python](https://passlib.readthedocs.io/en/stable/)\n* [Polars - fast DataFrame library for Rust and Python](https://docs.pola.rs/)\n* [Rich - Traceback and logging, made easy](https://rich.readthedocs.io/en/stable/traceback.html)\n* [Calamine - Excel reader in Rust](https://github.com/tafia/calamine)\n* [Inline Snapshots - pytest plugin for inline snapshots]()\n* [Connection pool for asyncpg](https://magicstack.github.io/asyncpg/current/usage.html#connection-pools)\n* [Granian - A Rust HTTP server for Python applications](https://github.com/emmett-framework/granian)\n* [APScheduler - In-process task scheduler with Cron-like capabilities](https://apscheduler.readthedocs.io/en/master/)\n* [Valkey - A simple and fast key-value store](https://github.com/valkey-io/valkey)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n## Change Log\n- **[long time ago...]** it was a long time ago in galaxy far far away...\n- **[JUN 4 2022]** alembic migrations added to project\n- **[JUN 6 2022]** initial dataset for shakespeare models\n- **[OCT 3 2022]** poetry added to project\n- **[NOV 12 2022]** ruff implemented to project as linting tool\n- **[FEB 14 2023]** bump project to Python 3.11\n- **[APR 10 2023]** implement logging with rich\n- **[APR 28 2023]** Rainbow logs with rich :rainbow:\n- **[JUL 7 2023]** migrate to pydantic 2.0 :fast_forward:\n- **[JUL 25 2023]** add user authentication with JWT and Redis as token storage :lock: :key:\n- **[SEP 2 2023]** add passlib and bcrypt for password hashing :lock: :key:\n- **[OCT 21 2023]** refactor shakespeare models to use sqlalchemy 2.0 :fast_forward:\n- **[FEB 1 2024]** bump project to Python 3.12 :fast_forward:\n- **[MAR 15 2024]** add polars and calamine to project :heart_eyes_cat:\n- **[JUN 8 2024]** implement asyncpg connection pool :fast_forward:\n- **[AUG 17 2024]** granian use case implemented with docker compose and rich logger :fast_forward:\n- **[OCT 16 2024]** apscheduler added to project :clock1:\n- **[DEC 16 2024]** bump project to Python 3.13 :fast_forward:\n- **[JAN 28 2025]** add SMTP setup :email:\n- **[MAR 8 2025]** switch from poetry to uv :fast_forward:\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n[contributors-shield]: https://img.shields.io/github/contributors/grillazz/fastapi-sqlalchemy-asyncpg.svg?style=for-the-badge\n[contributors-url]: https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/grillazz/fastapi-sqlalchemy-asyncpg.svg?style=for-the-badge\n[forks-url]: https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/network/members\n[stars-shield]: https://img.shields.io/github/stars/grillazz/fastapi-sqlalchemy-asyncpg.svg?style=for-the-badge\n[stars-url]: https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/stargazers\n[issues-shield]: https://img.shields.io/github/issues/grillazz/fastapi-sqlalchemy-asyncpg.svg?style=for-the-badge\n[issues-url]: https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/issues\n[license-shield]: https://img.shields.io/github/license/grillazz/fastapi-sqlalchemy-asyncpg.svg?style=for-the-badge\n[license-url]: https://github.com/grillazz/fastapi-sqlalchemy-asyncpg/blob/main/LICENSE\n[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge\u0026logo=linkedin\u0026colorB=555\n[linkedin-url]: https://www.linkedin.com/in/python-has-powers/\n\n[fastapi.tiangolo.com]: https://img.shields.io/badge/FastAPI-0.115.11-009485?style=for-the-badge\u0026logo=fastapi\u0026logoColor=white\n[fastapi-url]: https://fastapi.tiangolo.com/\n[pydantic.com]: https://img.shields.io/badge/Pydantic-2.10.6-e92063?style=for-the-badge\u0026logo=pydantic\u0026logoColor=white\n[pydantic-url]: https://docs.pydantic.dev/latest/\n[sqlalchemy.org]: https://img.shields.io/badge/SQLAlchemy-2.0.38-bb0000?color=bb0000\u0026style=for-the-badge\n[sqlalchemy-url]: https://docs.sqlalchemy.org/en/20/\n[uvicorn.org]: https://img.shields.io/badge/Uvicorn-0.34.0-2094f3?style=for-the-badge\u0026logo=uvicorn\u0026logoColor=white\n[uvicorn-url]: https://www.uvicorn.org/\n[asyncpg.github.io]: https://img.shields.io/badge/asyncpg-0.30.0-2e6fce?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white\n[asyncpg-url]: https://magicstack.github.io/asyncpg/current/\n[pytest.org]: https://img.shields.io/badge/pytest-8.3.5-fff?style=for-the-badge\u0026logo=pytest\u0026logoColor=white\n[pytest-url]: https://docs.pytest.org/en/6.2.x/\n[alembic.sqlalchemy.org]: https://img.shields.io/badge/alembic-1.15.1-6BA81E?style=for-the-badge\u0026logo=alembic\u0026logoColor=white\n[alembic-url]: https://alembic.sqlalchemy.org/en/latest/\n[rich.readthedocs.io]: https://img.shields.io/badge/rich-13.9.4-009485?style=for-the-badge\u0026logo=rich\u0026logoColor=white\n[rich-url]: https://rich.readthedocs.io/en/latest/\n[redis.io]: https://img.shields.io/badge/redis-5.2.1-dc382d?style=for-the-badge\u0026logo=redis\u0026logoColor=white\n[redis-url]: https://redis.io/\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrillazz%2Ffastapi-sqlalchemy-asyncpg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrillazz%2Ffastapi-sqlalchemy-asyncpg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrillazz%2Ffastapi-sqlalchemy-asyncpg/lists"}