Skip to content

Commit 4eb1b47

Browse files
committed
finish this version except readme
1 parent 0ad3e67 commit 4eb1b47

File tree

19 files changed

+93
-45
lines changed

19 files changed

+93
-45
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@
77
- Alembic migrations
88
- Very minimal project structure yet ready for quick start building new api
99
- Refresh token endpoint (not only access like in official template)
10-
- Two databases in docker-compose.yml (second for tests)
10+
- Two databases in docker-compose.yml (second one for tests)
1111
- poetry
1212
- `pre-push.sh` script with poetry export, autoflake, black, isort and flake8
13-
- Setup for tests, one big test for token flow and very extensible `conftest.py`
13+
- Setup for async tests, one func test for token flow and very extensible `conftest.py`
1414

1515
## What this repo is
1616

17-
This is a minimal template for FastAPI backend + postgresql db as of 2021, `async` style for database sessions, endpoints and tests. It provides basic codebase that almost every application has, but nothing more.
17+
This is a minimal template for FastAPI backend + postgresql db as of 2021.11, `async` style for database sessions, endpoints and tests. It provides basic codebase that almost every application has, but nothing more.
1818

1919
## What this repo is not
2020

21-
It is not complex, full featured solutions for all human kind problems. It doesn't include any third party that isn't necessary for most of apps (dashboards, queues) or implementation differs so much in every project that it's pointless (complex user model, emails).
21+
It is not complex, full featured solutions for all human kind problems. It doesn't include any third party that isn't necessary for most of apps (dashboards, queues) or implementation differs so much in every project that it's pointless (complex User model, emails, RBAC, permissions).
2222

2323
## Quickstart
2424

2525
```bash
26-
# You can even install it globally
26+
# Install cookiecutter globally
2727
pip install cookiecutter
2828

2929
# And cookiecutter this project :)
@@ -32,20 +32,20 @@ cookiecutter https://github.com/rafsaf/minimal-fastapi-postgres-template
3232
cd project_name
3333
# Poetry install (and activate environment!)
3434
poetry install
35-
# Databases
35+
# Setup two databases
3636
docker-compose up -d
3737
# Alembic migrations upgrade and initial_data.py script
3838
bash init.sh
3939
# And this is it:
40-
uvicorn app.main:app
40+
uvicorn app.main:app --reload
4141
```
4242

4343
tests:
4444

4545
```bash
46+
# Note, it will use second database declared in docker-compose.yml, not default one
4647
pytest
47-
# Note, it will use second database declared in docker-compose.yml, not default one like
48-
# in official template
48+
4949
```
5050

5151
## About
@@ -54,6 +54,6 @@ This project is heavily base on official template https://github.com/tiangolo/fu
5454

5555
`2.0` style SQLAlchemy API is good enough so there is no need to write everything in `crud` and waste our time... The `core` folder was also rewritten. There is great base for writting tests in `tests`, but I didn't want to write hundreds of them, I noticed that usually after changes in the structure of the project, auto tests are useless and you have to write them from scratch anyway (delete old ones...), hence less than more. Similarly with the `User` model, it is very modest, because it will be adapted to the project anyway (and there are no tests for these endpoints, you would remove them probably).
5656

57-
## Learn by example
57+
## Step by step example
5858

59-
Let's imagine we need to create API for a website where users brag about their dogs... or whatever, they just can crud dogs in user panel for some reason. We will add dummy model Dog to our API, with relation to the default table User and crud auth endpoints, then test it shortly.
59+
I always enjoy to to have some kind of example in templates (even if I don't like it much, _some_ parts may be useful and save my time...), so let's create `POST` endpoint for creating dogs.

{{cookiecutter.project_name}}/Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# See https://hub.docker.com/r/nginx/unit/
1+
# See https://unit.nginx.org/installation/#docker-images
2+
23
FROM nginx/unit:1.25.0-python3.9
34

45
ENV PYTHONUNBUFFERED 1
56

6-
# Nginx unit config and init.sh will be used at container startup
7+
# Nginx unit config and init.sh will be consumed at container startup.
78
COPY ./app/init.sh /docker-entrypoint.d/init.sh
89
COPY ./nginx-unit-config.json /docker-entrypoint.d/config.json
910
RUN chmod +x /docker-entrypoint.d/init.sh
@@ -17,7 +18,7 @@ COPY ./alembic ./alembic
1718
COPY ./alembic.ini .
1819
COPY ./requirements.txt .
1920

20-
# Requirements and then cleanup
21+
# Update, install requirements and then cleanup.
2122
RUN apt update && apt install -y python3-pip \
2223
&& pip3 install -r requirements.txt \
2324
&& apt remove -y python3-pip \

{{cookiecutter.project_name}}/alembic.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
script_location = alembic
66

77
# template used to generate migration files
8-
file_template = %%(year)d%%(month).2d%%(day).2d%%(hour).2d%%(minute).2d%%(second).2d_%%(rev)s_%%(slug)s
8+
file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d_%%(slug)s__%%(rev)s
99

1010
# sys.path path, will be prepended to sys.path if present.
1111
# defaults to the current working directory.

{{cookiecutter.project_name}}/alembic/env.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@
3131

3232

3333
def get_database_uri():
34-
if settings.ENVIRONMENT == "PYTEST":
35-
return settings.TEST_SQLALCHEMY_DATABASE_URI
3634
return settings.DEFAULT_SQLALCHEMY_DATABASE_URI
3735

3836

{{cookiecutter.project_name}}/alembic/versions/20211023161504_e2318cba28d4_init.py renamed to {{cookiecutter.project_name}}/alembic/versions/2021_11_09_1736_init__cefce371682e.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
"""init
22
3-
Revision ID: e2318cba28d4
3+
Revision ID: cefce371682e
44
Revises:
5-
Create Date: 2021-10-23 16:15:04.828924
5+
Create Date: 2021-11-09 17:36:41.970204
66
77
"""
88
from alembic import op
99
import sqlalchemy as sa
1010

1111

1212
# revision identifiers, used by Alembic.
13-
revision = 'e2318cba28d4'
13+
revision = 'cefce371682e'
1414
down_revision = None
1515
branch_labels = None
1616
depends_on = None
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from fastapi import APIRouter
2+
3+
from app.api.endpoints import auth, users
4+
5+
api_router = APIRouter()
6+
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
7+
api_router.include_router(users.router, prefix="/users", tags=["users"])

{{cookiecutter.project_name}}/app/api/api_v1/deps.py renamed to {{cookiecutter.project_name}}/app/api/deps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from app.models import User
1414
from app.session import async_session
1515

16-
reusable_oauth2 = OAuth2PasswordBearer(tokenUrl="v1/auth/access-token")
16+
reusable_oauth2 = OAuth2PasswordBearer(tokenUrl="auth/access-token")
1717

1818

1919
async def get_session() -> AsyncGenerator[AsyncSession, None]:

{{cookiecutter.project_name}}/app/api/api_v1/__init__.py renamed to {{cookiecutter.project_name}}/app/api/endpoints/__init__.py

File renamed without changes.

{{cookiecutter.project_name}}/app/api/api_v1/auth.py renamed to {{cookiecutter.project_name}}/app/api/endpoints/auth.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
from sqlalchemy.ext.asyncio import AsyncSession
99

1010
from app import schemas
11-
from app.api.routers import api_v1_router
12-
from app.api.api_v1 import deps
11+
from app.api import deps
1312
from app.core import security
1413
from app.core.config import settings
1514
from app.models import User
1615

17-
1816
router = APIRouter()
1917

2018

@@ -90,6 +88,3 @@ async def refresh_token(
9088
"refresh_token": refresh_token,
9189
"refresh_expire_at": refresh_expire_at,
9290
}
93-
94-
95-
api_v1_router.include_router(router, prefix="", tags=["users"])

{{cookiecutter.project_name}}/app/api/api_v1/users.py renamed to {{cookiecutter.project_name}}/app/api/endpoints/users.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from sqlalchemy.ext.asyncio import AsyncSession
55

66
from app import models, schemas
7-
from app.api.api_v1 import deps
7+
from app.api import deps
88
from app.core.security import get_password_hash
99

1010
router = APIRouter()

0 commit comments

Comments
 (0)