Comments (9)
Storing db models in same place is just a personal preference, but I feel like it's very usable in small applications/microservices.
You can use poetry in docker, either by exporting your dependencies as requirements.txt
in a multi-stage build or directly:
FROM python:3.10-slim as build
ENV POETRY_VERSION=1.1.14
RUN pip install poetry==$POETRY_VERSION
COPY ./pyproject.toml ./poetry.lock ./
RUN poetry export -f requirements.txt -o requirements.txt
FROM python:3.10-slim as final
WORKDIR /app
ENV PYTHONPATH=$PYTHONPATH:src
COPY --from=build requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt --no-cache-dir
COPY ./src ./src
COPY alembic.ini ./
...
from fastapi-best-practices.
@b-bokma I'm currently using kubernetes and it's really easy to store your k8s secrets and configmaps in same format as your pydantic models:
class DatabaseSettings(BaseSettings):
class Config:
env_prefix = "database_"
driver: str = "postgresql+asyncpg"
sync_driver = "postgresql+psycopg2"
name: str
username: str
password: str
host: str
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
template:
...
spec:
...
containers:
- name: fastapi
...
envFrom:
- secretRef:
name: app-database
prefix: database_
This also helps if you need to use same secret for different applications
So we have a different sets of secrets in different namespaces at this moment 😉
from fastapi-best-practices.
Hey, @ThirVondukr
Thank you for your kind words, I truly appreciate them!
- Although I find this suggestion very handy, I am not sure to advocate implicit solutions like PYTHONPATH modifications or
__init__
imports. We did put some models there when it was appropriate though, just not an "every package" practice I believe. - I agree, that CI is very important, but it feels like that recommendation doesn't fall into FastAPI best practices in particular.
- poetry is great, but I wish it would be easier to use it in docker containers :)
- Agree, I will add these suggestions.
- Agree, too many people were pointing it out. My key point was not to use other libraries but already installed ones though.
from fastapi-best-practices.
Yep, agree. We actually do store all DB models in one folder in a small service we have for transcoding.
Well, your example with multi-stage looks pretty neat and clean! I didn't like the examples I have seen online, but will definitely try your example.
from fastapi-best-practices.
I'd say there's also a "problem" with using sqlalchemy commits with fastapi.
Usually you should use .flush()
method to flush sql to database if you need a server-side generated data such as primary keys, you still can use nested transactions, but you don't need to in most cases.
If you use a typical get_session
dependency and commit inside of it then commit would actually happen after the response is sent, which can lead to client receiving 200/201 for example but data won't actually be saved:
async def get_session() -> AsyncIterable[AsyncSession]:
async with async_sessionmaker.begin() as session:
yield session
This could be avoided by either
- Committing manually in each request
- Using another framework/library to do DI for you
- (Best Option) Using a middleware to commit session in it
I think that also could be covered in this repo
from fastapi-best-practices.
Storing db models in same place is just a personal preference, but I feel like it's very usable in small applications/microservices.
You can use poetry in docker, either by exporting your dependencies as
requirements.txt
in a multi-stage build or directly:FROM python:3.10-slim as build ENV POETRY_VERSION=1.1.14 RUN pip install poetry==$POETRY_VERSION COPY ./pyproject.toml ./poetry.lock ./ RUN poetry export -f requirements.txt -o requirements.txt FROM python:3.10-slim as final WORKDIR /app ENV PYTHONPATH=$PYTHONPATH:src COPY --from=build requirements.txt . RUN pip install --upgrade pip && pip install -r requirements.txt --no-cache-dir COPY ./src ./src COPY alembic.ini ./ ...
I agree with the usage of poetry in combination with docker multi stage, this behavior is also suggested by official documentation.
Another thing I usually do is to create a install-poetry.sh
script with the poetry version specified inside, in this way there is only one point of trust used by both Docker and the Developer.
Then simply include it into the docker first stage:
RUN bash install-poetry.sh
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
from fastapi-best-practices.
First of all - it's an amazing set of best practices, I also want to share some things that I use:
Project Structure
src
could be added toPYTHONPATH
to avoid prefixing every app import withsrc
, IDEs like PyCharm also support that.Models also could be stored in same package, it's easier to import your models and make sure all modules were executed when you generate your migrations:
src/ db/ models/ __init__.py comments.py posts.py tags.py base.py dependencies.py
# __init__.py from . commends import Comment from . posts import Post from . tags import Tag __all__ = ["Comment", "Post", "Tag"]# Anywhere in the code from db.models import PostContinuous Integration
Absolutely use CI in gitlab/github to automate your tests and linters!
Dependency Management
Use poetry instead of requirements.txt, it's awesome!
Custom base model from day 0
This could also be used to enable
orm_mode
and set up customalias_generator
if client (for example a JS app) requires it.Use
Starlette's Config objectPydantic BaseSettings!Pydantic has its own class to manage environment variables:
class AppSettings(BaseSettings): class Config: env_prefix = "app_" domain: str
I am using the method described here as a way to split secrets over different environments with pydantic settings:
https://rednafi.github.io/digressions/python/2020/06/03/python-configs.html
from fastapi-best-practices.
Hey, @ThirVondukr
Thank you for your kind words, I truly appreciate them!
- Although I find this suggestion very handy, I am not sure to advocate implicit solutions like PYTHONPATH modifications or
__init__
imports. We did put some models there when it was appropriate though, just not an "every package" practice I believe.- I agree, that CI is very important, but it feels like that recommendation doesn't fall into FastAPI best practices in particular.
- poetry is great, but I wish it would be easier to use it in docker containers :)
- Agree, I will add these suggestions.
- Agree, too many people were pointing it out. My key point was not to use other libraries but already installed ones though.
I don't understand why not to use poetry right in docker?
It is possible and very convenient to use the groups of dependencies provided by poetry?
The workflow is the following:
- install poetry tool by pip (the problem can only be in the size of this tool)
- copy pyproject.toml and poetry.lock files
- set env variable
POETRY_VIRTUALENVS_CREATE
to false, not to create env in docker container - run
poetry install --only main --no-root
from fastapi-best-practices.
@PashaDem Because I personally don't think you need an extra dependency/tool inside of your docker container, if you need it for something - add it to your docker image.
from fastapi-best-practices.
Related Issues (20)
- How to start the project
- fast-api-docker-poetry using controller / service / repository pattern HOT 1
- API Rate Limits HOT 2
- Circular import HOT 1
- Questions about 3. Use Dependencies data valadation vs DB HOT 6
- No module named 'src' HOT 1
- Initialization of global clients HOT 3
- Use `run_in_threadpool` or not? HOT 2
- Pydantic 2+ HOT 2
- What are some best practices for Fastapi + Mongodb HOT 2
- Response Handling HOT 1
- Pydantic2 & double conversions (#22) HOT 5
- Where to place OAuth2 functions
- Could you recommend an actual project that employs this project structure? HOT 2
- Adding `exception_handlers` for mapping from exceptions to the error responses HOT 1
- Debugging HOT 1
- Update Links in Readme.md for Smoother Navigation
- -
- Pydantic v2 Async field validator HOT 1
- Database.py file was not presented in the documentation HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fastapi-best-practices.