Code Monkey home page Code Monkey logo

fastapi-boilerplate's Introduction

Hi there, I'm Igor 👋

👓 Short About Me

I like building things and exploring different kinds of stuff, but mostly I've been working with data for the past years - Engineering, Analytics and deploying data solutions. I also like studying music, languages and religion in my spare time.

  • 🌊 I’m from Rio de Janeiro
  • 📚 I’m currently learning more about Backend and Machine Learning Engineering
  • 🧮 I studied Applied Mathematics at the Federal University of Rio de Janeiro
  • 🎵 I play classical guitar
  • 🐶 I love dogs

🥋 Projects In Progress

🛠️ A few Technologies I use

💾 Data

Python Pandas DBT Snowflake SQL PowerBI Metabase Fivetran AWS Airflow

🕸️ Web

FastAPI HTML JavaScript Heroku

Other

Linux Docker PostgreSQL Pydantic SQLAlchemy Poetry Pytest BeautifulSoup Selenium Retool Stripe

🚧 Currently Working With

Data infrastructure and solutions at Cidadania4u as a Data Tech Lead

🔭 A Few of my Past Projects

  • @stripemetrics: Computing stripe metrics just like the dashboard with python.
  • @dexter: Data Exploration Terser - dealing with multiple pandas dataframes.
  • @nn-from-scratch: Teaching Neural Networks from Scratch with Numpy.
  • @python-intro: Python Intro - Teaching python for newbies (Portuguese).
  • @campusmobilebooks: Campus Mobile Ebooks - Ebooks on entrepreneurship, MVP and experimentation written for Campus Mobile (Portuguese).

📫 How to reach me

You can message me on LinkedIn or just email me at [email protected].

fastapi-boilerplate's People

Contributors

ahsansheraz avatar alessiobugetti avatar dimaioksha avatar eredden avatar gmirsky avatar igorbenav avatar luca-medeiros avatar lucasqr avatar rememberlenny avatar shreyassarve avatar yuriimotov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastapi-boilerplate's Issues

Inhance import system and folder structure

Inhance Import
condensing import statements for brevity:
from app.core import async_get_db, TokenData, is_rate_limited, logging
This makes imports more concise and groups related items together

folder structure
Moving schemas inside the version folder could enhance the overall project organization. It might make the versioning more intuitive.
I believe middlewares should be in separate folder thats tell what it contain not like cache middleware its inside app/core/cache.py
Also exceptions file should be folder for each "source of error" not sure about the right word for it but for other services/third parties should be in service.py file (as example) inside exceptions folder users as well UserNotFound as example

logging System
logger configrations are on a file but logger object is being declared on each folder you are using it in
this code from rate_limit.py file

from app.core.logger import logging
from app.schemas.rate_limit import sanitize_path

logger = logging.getLogger(__name__)

pool: ConnectionPool | None = None
client: Redis | None = None

logger = logging.getLogger(__name__) # its being declared twice

my suggestion will make it easier u will be only need to import the logger (object)
from app.core import ( logger, ...)

  • This is my first time opening a github issue
  • sorry for my bad english

Enhance logging System

logging configurations are on a file but logger object is being declared on each folder you are using it in
this code from rate_limit.py file

from app.core.logger import logging
from app.schemas.rate_limit import sanitize_path

logger = logging.getLogger(__name__)

pool: ConnectionPool | None = None
client: Redis | None = None

logger = logging.getLogger(__name__) # its being declared twice

my suggestion will make it easier to use, u will only need to import the logger (object) and use it directly instead of declaring it on each file you want to use it in
from app.core import ( logger, ...)

Enhance import packages system

condensing import statements for brevity:

from app.crud import crud_users, crud_tiers, crud_rate_limits

instead of

from app.crud.crud_users import crud_users
from app.crud.crud_tier import crud_tiers
from app.crud.crud_rate_limit import crud_rate_limits

This makes imports more concise and groups related items together

Add an admin panel

Can add an admin panel to this application that displays all user, posts etc?

Pre Commit

I create a pre commit file which will check this ruff, format of the staged code if format require it format the file and stop that commit and also check for prints if a print occur in the staged code it will throw an error and stop the commit.

this is the code for that pre commit
Screenshot 2024-01-01 100617

but for run this the system have pre-commit and flake8-print installed.

pip install pre-commit flake8-print

Disable automatic table creation

I'm running this inside of docker-compose, and I want more control over the migrations. It seems to re-create the "initial" tables (user, tier, post) every time I perform docker-compose up.

I don't want it to do that, I want to be able to run alembic (from inside a container, not on my local machine).

I cannot seem to disable this behavior. Where does the alembic migration that creates the post table live? I want to stop it.

Cannot create new model in database

Problem 1: When i create a new model, but when i run docker-compose. It's not exists in my database.

from datetime import UTC, datetime
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import DateTime, ForeignKey, String,Integer
from ..core.db.database import Base

class Template(Base):
    __tablename__ = "template"

    id: Mapped[int] = mapped_column("id", autoincrement=True, nullable=False, unique=True, primary_key=True, init=False)
    text: Mapped[str] = mapped_column(String)
    description: Mapped[str] = mapped_column(String)
    created_by: Mapped[int] = mapped_column(Integer, nullable=False)
    updated_by: Mapped[int] = mapped_column(Integer, nullable=False)
    deleted_by: Mapped[int] = mapped_column(Integer, nullable=False)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default_factory=lambda: datetime.now(UTC))
    updated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), default=None)
    deleted_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), default=None)
    is_deleted: Mapped[bool] = mapped_column(default=False, index=True)

Screenshots
CleanShot 2024-04-10 at 00 11 33@2x

Problem 2: When i migrating, my database has been delete all table. This is log migration

poetry run alembic revision --autogenerate
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.ddl.postgresql] Detected sequence named 'rate_limit_id_seq' as owned by integer column 'rate_limit(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_rate_limit_tier_id' on 'rate_limit'
INFO  [alembic.autogenerate.compare] Detected removed table 'rate_limit'
INFO  [alembic.ddl.postgresql] Detected sequence named 'token_blacklist_id_seq' as owned by integer column 'token_blacklist(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_token_blacklist_token' on 'token_blacklist'
INFO  [alembic.autogenerate.compare] Detected removed table 'token_blacklist'
INFO  [alembic.ddl.postgresql] Detected sequence named 'post_id_seq' as owned by integer column 'post(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_post_created_by_user_id' on 'post'
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_post_is_deleted' on 'post'
INFO  [alembic.autogenerate.compare] Detected removed table 'post'
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_user_email' on 'user'
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_user_is_deleted' on 'user'
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_user_tier_id' on 'user'
INFO  [alembic.autogenerate.compare] Detected removed index 'ix_user_username' on 'user'
INFO  [alembic.autogenerate.compare] Detected removed table 'user'
INFO  [alembic.autogenerate.compare] Detected removed table 'tier'
  Generating /src/migrations/versions/d02f4a524850_.py ...  done

Running via 'uvicorn' from scratch on M2 Macbook fails

Describe the bug or question
When running the project's "From Scratch" instructions, I get this error:

❯ poetry run uvicorn src.app.main:app --reload
INFO:     Will watch for changes in these directories: ['/path/to/project']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [37118] using StatReload
INFO:     Started server process [37122]
INFO:     Waiting for application startup.
ERROR:    Traceback (most recent call last):
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/starlette/routing.py", line 734, in lifespan
    async with self.lifespan_context(app) as maybe_state:
  File "/opt/homebrew/Cellar/[email protected]/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 210, in __aenter__
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/path/to/project/src/app/core/setup.py", line 92, in lifespan
    await create_tables()
  File "/path/to/project/src/app/core/setup.py", line 34, in create_tables
    async with engine.begin() as conn:
  File "/opt/homebrew/Cellar/[email protected]/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 210, in __aenter__
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 1055, in begin
    async with conn:
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/base.py", line 121, in __aenter__
    return await self.start(is_ctxmanager=True)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/ext/asyncio/engine.py", line 270, in start
    await greenlet_spawn(self.sync_engine.connect)
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 197, in greenlet_spawn
    result = context.throw(*sys.exc_info())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3279, in connect
    return self._connection_cls(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 145, in __init__
    self._dbapi_connection = engine.raw_connection()
                             ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 3303, in raw_connection
    return self.pool.connect()
           ^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 449, in connect
    return _ConnectionFairy._checkout(self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 1263, in _checkout
    fairy = _ConnectionRecord.checkout(pool)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 712, in checkout
    rec = pool._do_get()
          ^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 179, in _do_get
    with util.safe_reraise():
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/impl.py", line 177, in _do_get
    return self._create_connection()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 390, in _create_connection
    return _ConnectionRecord(self)
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 674, in __init__
    self.__connect()
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 900, in __connect
    with util.safe_reraise():
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/pool/base.py", line 896, in __connect
    self.dbapi_connection = connection = pool._invoke_creator(self)
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/engine/create.py", line 643, in connect
    return dialect.connect(*cargs, **cparams)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 616, in connect
    return self.loaded_dbapi.connect(*cargs, **cparams)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 937, in connect
    await_only(creator_fn(*arg, **kw)),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 127, in await_only
    return current.driver.switch(awaitable)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 192, in greenlet_spawn
    value = await result
            ^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connection.py", line 2329, in connect
    return await connect_utils._connect(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1017, in _connect
    raise last_error or exceptions.TargetServerAttributeNotMatched(
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 991, in _connect
    conn = await _connect_addr(
           ^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 828, in _connect_addr
    return await __connect_addr(params, True, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 873, in __connect_addr
    tr, pr = await connector
             ^^^^^^^^^^^^^^^
  File "/Users/username/Library/Caches/pypoetry/virtualenvs/fastapi-boilerplate-lraqQfQg-py3.12/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 744, in _create_ssl_connection
    tr, pr = await loop.create_connection(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "uvloop/loop.pyx", line 1978, in create_connection
socket.gaierror: [Errno 8] nodename nor servname provided, or not known

ERROR:    Application startup failed. Exiting.

Description
As you can see, Redis & PostgreSQL containers are running as per the instructions:

image

I'm running this example on an M2 Macbook Air with macOS 14 (Sonoma), and every "solution" I could dig up so far (changing hostname, adding stuff to /etc/hosts) did not work ..

Thanks for creating boiler plate for FastAPI

Hello Igor,

I hope this message finds you well. I wanted to take a moment to express my appreciation for your development of the FastAPI-boilerplate. Its relevance and utility are undeniable, particularly given FastAPI's rapidly growing popularity.

I'm reaching out to introduce you to a project I've recently been working on, which aligns well with FastAPI's ethos of efficiency and modernity. It's a GitHub app named Snorkell.ai, designed specifically for FastAPI projects like yours.

Here's how Snorkell.ai can streamline your documentation process:

  1. Integration: Simply add Snorkell.ai to your repository. It's a straightforward process, involving just a few clicks on the GitHub app installation page.

  2. Automatic Documentation Generation: Once Snorkell.ai is part of your project, it automatically generates documentation for all your Python functions. This happens in the background, requiring no manual effort on your part.

  3. Real-Time Updates: Snorkell.ai is not just a one-time setup tool. It dynamically updates the documentation in response to any modifications you make to your functions. This ensures that your documentation always stays current with your codebase.

  4. Pull Request (PR) for Review: For every update, Snorkell.ai creates a PR containing the updated documentation. This allows you to review and merge the changes, ensuring that you maintain oversight and control over your project's documentation.

Implementing Snorkell.ai could significantly enhance the efficiency of maintaining your project's documentation, allowing you more time to focus on development. I believe it could be a valuable asset to your workflow.

Thank you for considering this tool. I'm looking forward to any thoughts or feedback you might have.

Demo Video: https://youtu.be/rXMW1xAA-RU

Best regards,
Suman

Remove `allow_reuse`

PydanticDeprecatedSince20: `allow_reuse` is deprecated and will be ignored; it should no longer be necessary. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/

🔭Roadmap

🔭To Do

Not exactly a roadmap, more of a possible TODO kind of list:

⚡️API

  • Add a photo upload endpoint for users
  • Add possibility of comments in posts
  • Add webhook to notify when a new comment is added in post

🧪Tests

  • Add MyPy
  • SQLite db for tests

✅Done

  • Add Ruff linter #83 #92 by @luca-medeiros
  • 🚀Token Refresh #63
  • 🚀Gunicorn NGINX deployment #56
  • 🚀get_joined in CRUD #53
  • ⚡️Expire jwt token (blacklist) #52
  • 📝Warn to make sure DB and tables are created before running create_superuser and create_tier scripts #40
  • 📝Remind to pass "api/v1/..." in the path for rate_limiter #40
  • 📝Update directory structure #40
  • 📝Add "create_first_*" for scripts #40
  • 🚀Add a Rate Limiter dependency #37

typing.Dict, typing.List, typing.Type, ... deprecated

With ruff check:

src/app/api/paginated.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/paginated.py:1:1: UP035 `typing.List` is deprecated, use `list` instead
src/app/api/v1/login.py:2:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/logout.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/posts.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/rate_limits.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/tasks.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/tiers.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/api/v1/users.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/core/security.py:2:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/core/setup.py:1:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/core/utils/cache.py:5:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/core/utils/cache.py:5:1: UP035 `typing.List` is deprecated, use `list` instead
src/app/core/utils/cache.py:5:1: UP035 `typing.Tuple` is deprecated, use `tuple` instead
src/app/crud/crud_base.py:2:1: UP035 `typing.Dict` is deprecated, use `dict` instead
src/app/crud/crud_base.py:2:1: UP035 `typing.List` is deprecated, use `list` instead
src/app/crud/crud_base.py:2:1: UP035 `typing.Type` is deprecated, use `type` instead
src/app/crud/helper.py:1:1: UP035 `typing.List` is deprecated, use `list` instead
src/app/crud/helper.py:1:1: UP035 `typing.Type` is deprecated, use `type` instead
Found 19 errors.

Migrate pydantic validators to field_validators

In src/app/schemas/rate_limit.py:

PydanticDeprecatedSince20: Pydantic V1 style `@validator` validators are deprecated. You should migrate to Pydantic V2 style `@field_validator` validators, see the migration guide for more details. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.4/migration/

Replace SQLAlchemy & Pydantic with SQLModel

Since the author of FastAPI created SQLModel in order to be able to reduce the amount of code being maintained by combining models of both libraries, how about replacing them with an SQLModel based solution? :wink

Enhance folder structure

Moving schemas inside the version folder could enhance the overall project organization. It might make the versioning more intuitive.
I believe middlewares should be in separate folder that's tell what it contain not like cache middleware its inside app/core/cache.py
Also exceptions file should be folder for each "source of error" not sure about the right word for it but for other services/third parties should be in service.py file (as example) inside exceptions folder users as well UserNotFound as example

nginx failed

docker compose up

fastapi-boilerplate-db-1 | 2024-02-06 05:51:59.250 UTC [27] LOG: database system was shut down at 2024-02-06 05:51:57 UTC
fastapi-boilerplate-db-1 | 2024-02-06 05:51:59.260 UTC [1] LOG: database system is ready to accept connections
fastapi-boilerplate-web-1 | /bin/sh: 1:
fastapi-boilerplate-web-1 | [gunicorn,: not found

Don't return arrays as top level responses

The top level response from an endpoint should always be an object, never an array.
The problem is that it's very hard to make backwards compatible changes when you return arrays. Objects let you make additive changes.

# GOOD
GET /api/v1/users returns:
{ "data": [{ ...user1...}, { ...user2...}] }

# BAD
GET /api/v1/users returns:
[{ ...user1...}, { ...user2...}]

The obvious common evolution in this specific example will be to add pagination. You can always add totalCount or hasMore fields and old clients will continue to work. If your endpoint returns a top-level array, you will need a whole new endpoint.

Add prometheus/grafana metrics dashboard + (loki, tempo for logging)

Is your feature request related to a problem? Please describe.
Not really a problem. More of a standalone improvement for the current logging + adding metrics dashboard.

Describe the solution you'd like
I propose the integration of a Prometheus/Grafana-based metrics dashboard into the library. This would offer real-time monitoring capabilities, allowing users to visualize key performance metrics. Also, incorporating Loki and Tempo for logging would significantly enhance our ability to perform more efficient and effective log analysis and tracing.

Describe alternatives you've considered
Not many other OSS monitoring tools to consider in this space.

Additional context
image
image
image
image

Move worker script

Create a worker folder inside core, move the worker logic to this new folder

Switch from UUID v4 to v7

Describe the solution you'd like
Migrate to using UUID v7 (uuid6 package, which despite its name provides uuid7() fn) as data type for id columns.

Additional context
These articles outline advantages of v7 (as opposed to v4), and also some pitfalls of not doing so:

Link 1 comes with very detailed information about all UUID implementations (benchmarks included), Link 2 provides a well-rounded writeup on implications for PostgreSQL in particular!

Swagger documentation not getting generated

Describe the bug or question
The swagger documentation is not appearing while running the app locally.

To Reproduce

  1. Ensure the pre-requisites are up and running (db, redis)

  2. Create and add the suggested configuration in .env file for running the application locally

  3. Start the application locally using the below command and open the following URL in a browser: http://127.0.0.1:8000/docs

    poetry run uvicorn src.app.main:app --reload

Description
On opening the swagger endpoint, the following message is shown on the browser: "No operations defined in spec!"

Screenshots
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.