Welcome to my project 📁, his project is the core of a bigger application. This is intended to be used as a template. I am also using this project to learn 🤓 please leave any recommendations.
📓 I followed the best practices described in this Repository.
🌟 Based on the project from Tiangolo's Full Stack Template.
To setup locally please follow the following steps
-
Install
Postgresql
locally or in a docker container and update the.env
file with the following credentials:# Postgres POSTGRES_SERVER= <Your_host_name> POSTGRES_PORT= <Available_post> POSTGRES_DB= <Your_database> POSTGRES_USER= <Your_user> POSTGRES_PASSWORD= <Your_password>
-
Install the
libpq
package.For Mac:
First install the package globally, using:
brew install libpq
After installing, link the library so it's available system-wide, with:
brew link libpq --force
For Linux:
sudo apt-get install libpq-dev # Debian/Ubuntu sudo dnf install postgresql-libs # Fedora
For Windows:
!!! Please research and add the steps here !!!
-
Create a virtual environment
./venv/
in the base directoty and activate it.For Mac or Linux:
Create and then run the environment, using:
python3 -m venv venv
source venv/bin/activate
For Windows:
Create and run the environment, with:
python3 -m venv venv
venv\Scripts\activate
-
Install the development requirements in
./requirements/dev.txt
, run the following command:For Mac, Linux or Windows:
pip install -r requirements/dev.txt
-
Create a .env file with the following contents:
# Domain # This would be set to the production domain with an env var on deployment # used by Traefik to transmit traffic and aqcuire TLS certificates DOMAIN=localhost # Environment: local, staging, production ENVIRONMENT=local PROJECT_NAME="API Project" STACK_NAME=api-project # Backend BACKEND_CORS_ORIGINS="http://localhost,http://localhost:5173,https://localhost,https://localhost:5173" SECRET_KEY=changethis # First Super User FIRST_SUPERUSER_FIRST_NAME=john FIRST_SUPERUSER_LAST_NAME=doe FIRST_SUPERUSER=admin FIRST_SUPERUSER_PASSWORD=hardpassword FIRST_SUPERUSER_PHONENUMBER= # With extension example: '+11234567890' FIRST_SUPERUSER_EMAIL= FIRST_ROLE= FIRST_SUPERUSER_BIRTHDAY= # Emails SMTP_HOST= SMTP_USER= SMTP_PASSWORD= EMAILS_FROM_EMAIL=info@example.com SMTP_TLS=True SMTP_SSL=False SMTP_PORT=587 EMAIL_RESET_TOKEN_EXPIRE_HOURS= # Postgres POSTGRES_SERVER=localhost POSTGRES_PORT=5432 POSTGRES_DB= POSTGRES_USER= POSTGRES_PASSWORD= SENTRY_DSN= # Uploads Server UPLOADS_URL=
-
Start the PostgreSQL server.
-
Apply the migrations to the database, using:
alembic upgrade head
-
Run the RESTAPI using a debuger in
.vscode/launch.json
or using command:fastapi dev src/main.py
-
Using MailHog SMTP Server (for testing emails):
To run this service please make sure that the following environment variables are set:
# Code above omitted 👆 # Emails SMTP_HOST=local SMTP_USER= SMTP_PASSWORD= EMAILS_FROM_EMAIL=info@example.com SMTP_TLS=False SMTP_SSL=False SMTP_PORT=1025 # Code bellow omitted 👇
9.1 Install and start MailHog by running:
For Mac:
brew update && brew install mailhog
mailhog
For Linux (Debian or Ubuntu)
sudo apt-get -y install golang-go go get github.com/mailhog/MailHog
/path/to/MailHog # The path to the MailHog installation.
The service will catch the outgoing email and display it at
http://localhost:8025
.
To create a email template the project uses mjml, a markup language used for designing responsive HTML emails.
-
Install mjml's Visual Studio Code extension.
Press
F1
and typeext install vscode-mjml
. -
Create a
.mjml
file in thesrc/mail/templates/src
. -
To preview the contents press
F1
orCtrl+Shift+P
and typeMJML: Open Preview to the Side
. -
To generate the html file press
F1
orCtrl+Shift+P
and typeMJML: Export HTML
modify the file name and save it pressingEnter ↩️
.
For testing an in-memory data base is used. You can check the configurations in the conftest.py
file.
I recommend reading about fixtures, which are a very useful feature of pytest and are heavily use in this project.
Aim to test 80-90% of your code. 🤯
-
Create a directory with the same name that the package in the
src/
directory it will test.├── src/ │ └── auth/ ├── tests/ └── auth/
-
Inside the folder create files with the
test_
prefix or_test
sufix to test the individual modules (router, service, etc.).├── src/ │ └── auth/ │ ├── router.py │ └── service.py ├── tests/ └── auth/ ├── test_router.py └── service_test.py
-
Create the necesary test(s). These should be independent from each other!
-
Run the tests with the commands:
Running all tests:
pytest
Running all tests in a test_ file:
pytest tests/route/to/test_file_name.py
Running a specific test in a test_ file:
pytest tests/route/to/test_file_name.py::test_function_name
Pay attention to the way the endpoint takes data as query parameters or as a request body.
-
Query parameters:
r = client.get( url=f"{settings.API_V1_STR}/example/path/{parameter}" )
-
Form data:
data_body = { "parameter1": value, "parameter2": value } r = client.post( url=f"{settings.API_V1_STR}/example/path/", headers=example_headers, data=data_body, # <- Changes here )
-
Request body:
data_body = { "parameter1": value, "parameter2": value } r = client.post( url=f"{settings.API_V1_STR}/example/path/", headers=example_headers, json=data_body, # <- Changes here )
Make sure that the created fixtures
are properly scoped. Properly clean up test data. Feel free to leave any recommendations for this problem.
For more information about testing check out this video from freeCodeCamp.org (🔥).
It is recommended to create a new folder for each module, for example to create a customers
application:
-
Create a folder in the
src/
directory:├── src/ └── customers/
-
Create a
models.py
file inside this folder.├── src/ └── customers/ └── models.py
-
Add the tables into the file with SQLModel.
from sqlmodel import SQLModel class Customer(SQLModel, table= True): id: int | None = Field(default=None, primary_key=True) first_name: str = Field(max_length=50) last_name: str = Field(max_length=50) birthday: date phone_number: int # Add all the necessary columns and models here 👇
To create the alembic revision correctly follow the steps:
-
Import the model to the global models:
├── src/ └── models.py
Add the model there:
# Add all the models to this file in order to generate automatic migrations from src.customers.models import * # Code omited below 👇
-
Run the command:
alembic revision --autogenerate -m "Added a customers table."
-
Check the newly generated revision, add the
sqlmodel
library import:# code omited above 👆 import sqlmodel # code omited bellow 👇
-
Finally upgrade the data base, running:
alembic upgrade head
In order to properly understand Tiangolo's project and start developing, the following resources 🔗 were helpful for me:
- The ⚡ FastAPI official documentation.
- The 🧰 SQLModel official documentation.
- The 🔍 Pydantic official documentation.
- The 📧 MJML official documentation.
- The 🧪 Pytest official documentation.