Skip to content

Commit db94277

Browse files
authored
Merge pull request #65 from igorbenav/folder-structure
Folder structure
2 parents 36d0493 + 0234a91 commit db94277

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+195
-194
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ WORKDIR /tmp
66

77
RUN pip install poetry
88

9-
COPY src/pyproject.toml src/poetry.lock* /tmp/
9+
COPY ./pyproject.toml ./poetry.lock* /tmp/
1010

1111
RUN poetry export -f requirements.txt --output requirements.txt --without-hashes
1212

README.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ So you may skip to [5. Extending](#5-extending).
269269
### 4.2 From Scratch
270270

271271
#### 4.2.1. Packages
272-
In the `src` directory, run to install required packages:
272+
In the `root` directory (`FastAPI-boilerplate` if you didn't change anything), run to install required packages:
273273
```sh
274274
poetry install
275275
```
@@ -330,9 +330,9 @@ redis:alpine
330330
```
331331

332332
#### 4.2.4. Running the API
333-
While in the `src` folder, run to start the application with uvicorn server:
333+
While in the `root` folder, run to start the application with uvicorn server:
334334
```sh
335-
poetry run uvicorn app.main:app --reload
335+
poetry run uvicorn src.app.main:app --reload
336336
```
337337
> [!TIP]
338338
> The --reload flag enables auto-reload once you change (and save) something in the project
@@ -345,7 +345,7 @@ poetry run uvicorn app.main:app --reload
345345
346346
If you are using docker compose, you should uncomment this part of the docker-compose.yml:
347347
```
348-
# #-------- uncomment to create first superuser --------
348+
#-------- uncomment to create first superuser --------
349349
# create_superuser:
350350
# build:
351351
# context: .
@@ -391,9 +391,9 @@ docker-compose stop create_superuser
391391
```
392392

393393
#### 4.3.2 From Scratch
394-
While in the `src` folder, run (after you started the application at least once to create the tables):
394+
While in the `root` folder, run (after you started the application at least once to create the tables):
395395
```sh
396-
poetry run python -m scripts.create_first_superuser
396+
poetry run python -m src.scripts.create_first_superuser
397397
```
398398

399399
### 4.3.3 Creating the first tier
@@ -423,15 +423,21 @@ First, you may want to take a look at the project structure and understand what
423423
```sh
424424
.
425425
├── Dockerfile # Dockerfile for building the application container.
426-
├── LICENSE.md # License file for the project.
427-
├── README.md # Project README providing information and instructions.
428426
├── docker-compose.yml # Docker Compose file for defining multi-container applications.
427+
├── pyproject.toml # Poetry configuration file with project metadata and dependencies.
428+
├── README.md # Project README providing information and instructions.
429+
├── LICENSE.md # License file for the project.
430+
431+
├── tests # Unit and integration tests for the application.
432+
│ ├── __init__.py
433+
│ ├── conftest.py # Configuration and fixtures for pytest.
434+
│ ├── helper.py # Helper functions for tests.
435+
│ └── test_user.py # Test cases for user-related functionality.
429436
430437
└── src # Source code directory.
431438
├── __init__.py # Initialization file for the src package.
432439
├── alembic.ini # Configuration file for Alembic (database migration tool).
433440
├── poetry.lock # Poetry lock file specifying exact versions of dependencies.
434-
├── pyproject.toml # Poetry configuration file with project metadata and dependencies.
435441
436442
├── app # Main application directory.
437443
│ ├── __init__.py # Initialization file for the app package.
@@ -517,16 +523,10 @@ First, you may want to take a look at the project structure and understand what
517523
│ └── versions # Individual migration scripts.
518524
│ └── README.MD
519525
520-
├── scripts # Utility scripts for the application.
521-
│ ├── __init__.py
522-
│ ├── create_first_superuser.py # Script to create the first superuser.
523-
│ └── create_first_tier.py # Script to create the first user tier.
524-
525-
└── tests # Unit and integration tests for the application.
526+
└── scripts # Utility scripts for the application.
526527
├── __init__.py
527-
├── conftest.py # Configuration and fixtures for pytest.
528-
├── helper.py # Helper functions for tests.
529-
└── test_user.py # Test cases for user-related functionality.
528+
├── create_first_superuser.py # Script to create the first superuser.
529+
└── create_first_tier.py # Script to create the first user tier.
530530
```
531531

532532
### 5.2 Database Model
@@ -1139,9 +1139,9 @@ async def get_task(task_id: str):
11391139
And finally run the worker in parallel to your fastapi application.
11401140

11411141
If you are using `docker compose`, the worker is already running.
1142-
If you are doing it from scratch, run while in the `src` folder:
1142+
If you are doing it from scratch, run while in the `root` folder:
11431143
```sh
1144-
poetry run arq app.worker.WorkerSettings
1144+
poetry run arq src.app.worker.WorkerSettings
11451145
```
11461146
### 5.11 Rate Limiting
11471147
To limit how many times a user can make a request in a certain interval of time (very useful to create subscription plans or just to protect your API against DDOS), you may just use the `rate_limiter` dependency:
@@ -1301,14 +1301,14 @@ docker compose up
13011301
```
13021302

13031303
If you are doing it from scratch, ensure your postgres and your redis are running, then
1304-
while in the `src` folder, run to start the application with uvicorn server:
1304+
while in the `root` folder, run to start the application with uvicorn server:
13051305
```sh
1306-
poetry run uvicorn app.main:app --reload
1306+
poetry run uvicorn src.app.main:app --reload
13071307
```
13081308

13091309
And for the worker:
13101310
```sh
1311-
poetry run arq app.worker.WorkerSettings
1311+
poetry run arq src.app.worker.WorkerSettings
13121312
```
13131313

13141314
## 6. Running in Production
@@ -1366,7 +1366,7 @@ To run with NGINX, you start by uncommenting the following part in your `docker-
13661366
# docker-compose.yml
13671367

13681368
...
1369-
# #-------- uncomment to run with nginx --------
1369+
#-------- uncomment to run with nginx --------
13701370
# nginx:
13711371
# image: nginx:latest
13721372
# ports:
@@ -1501,20 +1501,20 @@ Now, to run:
15011501
### 7.1 Docker Compose
15021502
First you need to uncomment the following part in the `docker-compose.yml` file:
15031503
```
1504-
# #-------- uncomment to run tests --------
1504+
#-------- uncomment to run tests --------
15051505
# pytest:
15061506
# build:
15071507
# context: .
15081508
# dockerfile: Dockerfile
15091509
# env_file:
1510-
# - ./src/.env
1510+
# - ./src/.env
15111511
# depends_on:
15121512
# - db
15131513
# - create_superuser
15141514
# - redis
1515-
# command: python -m pytest
1515+
# command: python -m pytest ./tests
15161516
# volumes:
1517-
# - ./src:/code/src
1517+
# - .:/code
15181518
```
15191519

15201520
You'll get:
@@ -1525,14 +1525,14 @@ You'll get:
15251525
context: .
15261526
dockerfile: Dockerfile
15271527
env_file:
1528-
- ./src/.env
1528+
- ./src/.env
15291529
depends_on:
15301530
- db
15311531
- create_superuser
15321532
- redis
1533-
command: python -m pytest
1533+
command: python -m pytest ./tests
15341534
volumes:
1535-
- ./src:/code/src
1535+
- .:/code
15361536
```
15371537

15381538
Start the Docker Compose services:
@@ -1548,7 +1548,7 @@ docker-compose run --rm pytest
15481548

15491549
### 7.2 From Scratch
15501550

1551-
While in the `src` folder, run:
1551+
While in the `root` folder, run:
15521552
```sh
15531553
poetry run python -m pytest
15541554
```
@@ -1557,7 +1557,7 @@ poetry run python -m pytest
15571557
Contributions are appreciated, even if just reporting bugs, documenting stuff or answering questions. To contribute with a feature:
15581558
1. Fork it (https://github.com/igormagalhaesr/FastAPI-boilerplate)
15591559
2. Create your feature branch (`git checkout -b feature/fooBar`)
1560-
3. Test your changes while in the src folder `poetry run python -m pytest`
1560+
3. Test your changes while in the root folder `poetry run python -m pytest`
15611561
4. Commit your changes (`git commit -am 'Add some fooBar'`)
15621562
5. Push to the branch (`git push origin feature/fooBar`)
15631563
6. Create a new Pull Request

docker-compose.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ services:
5050
expose:
5151
- "6379"
5252

53-
# #-------- uncomment to run with nginx --------
53+
#-------- uncomment to run with nginx --------
5454
# nginx:
5555
# image: nginx:latest
5656
# ports:
@@ -60,7 +60,7 @@ services:
6060
# depends_on:
6161
# - web
6262

63-
# #-------- uncomment to create first superuser --------
63+
#-------- uncomment to create first superuser --------
6464
# create_superuser:
6565
# build:
6666
# context: .
@@ -80,16 +80,16 @@ services:
8080
# context: .
8181
# dockerfile: Dockerfile
8282
# env_file:
83-
# - ./src/.env
83+
# - ./src/.env
8484
# depends_on:
8585
# - db
8686
# - create_superuser
8787
# - redis
88-
# command: python -m pytest
88+
# command: python -m pytest ./tests
8989
# volumes:
90-
# - ./src:/code/src
90+
# - .:/code
9191

92-
# #-------- uncomment to create first tier --------
92+
#-------- uncomment to create first tier --------
9393
# create_tier:
9494
# build:
9595
# context: .
File renamed without changes.

src/app/api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from fastapi import APIRouter
22

3-
from app.api.v1 import router as v1_router
3+
from ..api.v1 import router as v1_router
44

55
router = APIRouter(prefix="/api")
66
router.include_router(v1_router)

src/app/api/dependencies.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
from typing import Annotated, Union, Any
22

3-
from app.core.security import SECRET_KEY, ALGORITHM, oauth2_scheme
4-
from app.core.config import settings
5-
63
from sqlalchemy.ext.asyncio import AsyncSession
74
from jose import JWTError, jwt
85
from fastapi import (
@@ -11,17 +8,19 @@
118
Request
129
)
1310

14-
from app.core.exceptions.http_exceptions import UnauthorizedException, ForbiddenException, RateLimitException
15-
from app.core.db.database import async_get_db
16-
from app.core.logger import logging
17-
from app.core.schemas import TokenData
18-
from app.core.utils.rate_limit import is_rate_limited
19-
from app.core.security import verify_token
20-
from app.crud.crud_rate_limit import crud_rate_limits
21-
from app.crud.crud_tier import crud_tiers
22-
from app.crud.crud_users import crud_users
23-
from app.models.user import User
24-
from app.schemas.rate_limit import sanitize_path
11+
from ..core.security import oauth2_scheme
12+
from ..core.config import settings
13+
from ..core.exceptions.http_exceptions import UnauthorizedException, ForbiddenException, RateLimitException
14+
from ..core.db.database import async_get_db
15+
from ..core.logger import logging
16+
from ..core.schemas import TokenData
17+
from ..core.utils.rate_limit import is_rate_limited
18+
from ..core.security import verify_token
19+
from ..crud.crud_rate_limit import crud_rate_limits
20+
from ..crud.crud_tier import crud_tiers
21+
from ..crud.crud_users import crud_users
22+
from ..models.user import User
23+
from ..schemas.rate_limit import sanitize_path
2524

2625
logger = logging.getLogger(__name__)
2726

@@ -37,7 +36,7 @@ async def get_current_user(
3736
raise UnauthorizedException("User not authenticated.")
3837

3938
if "@" in token_data.username_or_email:
40-
user: dict = await crud_users.get(db=db, email=token_data.username_or_email, is_deleted=False)
39+
user: dict | None = await crud_users.get(db=db, email=token_data.username_or_email, is_deleted=False)
4140
else:
4241
user = await crud_users.get(db=db, username=token_data.username_or_email, is_deleted=False)
4342

src/app/api/v1/__init__.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from fastapi import APIRouter
22

3-
from app.api.v1.login import router as login_router
4-
from app.api.v1.logout import router as logout_router
5-
from app.api.v1.users import router as users_router
6-
from app.api.v1.posts import router as posts_router
7-
from app.api.v1.tasks import router as tasks_router
8-
from app.api.v1.tiers import router as tiers_router
9-
from app.api.v1.rate_limits import router as rate_limits_router
3+
from .login import router as login_router
4+
from .logout import router as logout_router
5+
from .users import router as users_router
6+
from .posts import router as posts_router
7+
from .tasks import router as tasks_router
8+
from .tiers import router as tiers_router
9+
from .rate_limits import router as rate_limits_router
1010

1111
router = APIRouter(prefix="/v1")
1212
router.include_router(login_router)

src/app/api/v1/login.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
from typing import Annotated, Dict
2-
from datetime import timedelta, datetime, timezone
2+
from datetime import timedelta
33

44
from fastapi import Response, Request, Depends
55
from fastapi.security import OAuth2PasswordRequestForm
66
from sqlalchemy.ext.asyncio import AsyncSession
77
import fastapi
88

9-
from app.core.config import settings
10-
from app.core.db.database import async_get_db
11-
from app.core.exceptions.http_exceptions import UnauthorizedException
12-
from app.core.schemas import Token
13-
from app.core.security import (
9+
from ...core.config import settings
10+
from ...core.db.database import async_get_db
11+
from ...core.exceptions.http_exceptions import UnauthorizedException
12+
from ...core.schemas import Token
13+
from ...core.security import (
1414
ACCESS_TOKEN_EXPIRE_MINUTES,
1515
create_access_token,
1616
authenticate_user,

src/app/api/v1/logout.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
from sqlalchemy.ext.asyncio import AsyncSession
55
from jose import JWTError
66

7-
from app.core.security import oauth2_scheme, blacklist_token
8-
from app.core.db.database import async_get_db
9-
from app.core.exceptions.http_exceptions import UnauthorizedException
7+
from ...core.security import oauth2_scheme, blacklist_token
8+
from ...core.db.database import async_get_db
9+
from ...core.exceptions.http_exceptions import UnauthorizedException
1010

1111
router = APIRouter(tags=["login"])
1212

0 commit comments

Comments
 (0)