Skip to content

Commit 14be2f4

Browse files
committed
some improvements and clean
1 parent 97383b7 commit 14be2f4

10 files changed

Lines changed: 52 additions & 44 deletions

File tree

docker/docker-compose.yaml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
version: "3.7"
2+
name: fullstack-template
23

34
services:
45
db:
56
image: postgres:17
6-
container_name: postgresql1
7-
restart: always
7+
container_name: fullstack-template-db
88
environment:
99
POSTGRES_USER: admin
1010
POSTGRES_PASSWORD: admin
@@ -14,14 +14,13 @@ services:
1414
ports:
1515
- "5434:5434"
1616
volumes:
17-
- postgres_data:/var/lib/postgresql/data
17+
- postgres_data_fullstack_template:/var/lib/postgresql/data
1818

1919
backend:
2020
container_name: fastapi-backend
2121
build:
2222
context: ../fastapi-postgres
2323
dockerfile: ../docker/DockerfileFastapi
24-
restart: always
2524
depends_on:
2625
- db
2726
environment:
@@ -36,7 +35,6 @@ services:
3635
args:
3736
APP_DIR: "vue3"
3837
VITE_API_URL: "http://localhost:5001"
39-
restart: always
4038
ports:
4139
- "3355:80"
4240

@@ -48,11 +46,10 @@ services:
4846
args:
4947
APP_DIR: "react"
5048
VITE_API_URL: "http://localhost:5001"
51-
restart: always
5249
ports:
5350
- "3366:80"
5451

5552

5653

5754
volumes:
58-
postgres_data:
55+
postgres_data_fullstack_template:

fastapi-postgres/app/__init__.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,23 @@ def create_app(docs=False) -> FastAPI:
2626
)
2727

2828
@app.exception_handler(HTTPException)
29-
async def validation_exception_handler(request, exc: HTTPException):
29+
async def http_exception_handler(request, exc: HTTPException):
3030
return JSONResponse(
31-
content=dict(message=f"error in response value {exc.detail}"),
31+
content={"message": f"error in response value {exc.detail}"},
3232
status_code=exc.status_code,
3333
)
3434

3535
@app.exception_handler(ValidationError)
36-
async def validation_exception_handler(request, exc: ValidationError):
36+
async def pydantic_validation_exception_handler(request, exc: ValidationError):
3737
return JSONResponse(
38-
content=dict(message=f"error in response value {exc}"),
38+
content={"message": f"error in response value {exc}"},
3939
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
4040
)
4141

4242
@app.exception_handler(RequestValidationError)
43-
async def validation_exception_handler(request, exc: RequestValidationError):
43+
async def request_validation_exception_handler(
44+
request, exc: RequestValidationError
45+
):
4446
errors = []
4547
for err in exc.errors():
4648
loc = err["loc"]

fastapi-postgres/app/routers/crud.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import List, Type
1+
from typing import Type
22

33
from fastapi import APIRouter, Body, Depends, HTTPException
44

@@ -11,7 +11,7 @@ def generate_crud_routes(
1111
model: Type[DBModel],
1212
prefix: str,
1313
require_token: bool = True,
14-
allowed_methods: List[str] = ["read", "add", "edit", "delete"],
14+
allowed_methods: list[str] = ["read", "add", "edit", "delete"],
1515
):
1616
router = APIRouter(prefix=f"/{prefix}", tags=[prefix])
1717

@@ -31,7 +31,7 @@ def _plain_filter(
3131

3232
if "read" in allowed_methods:
3333

34-
@router.post("", response_model=List[response_payload] | response_payload)
34+
@router.post("", response_model=list[response_payload] | response_payload)
3535
async def fetch_rows(
3636
pagination: Pagination = Depends(),
3737
filter_query: FilterQuery = filter_dep,
@@ -54,7 +54,7 @@ async def delete_rows(
5454

5555
if "add" in allowed_methods or "edit" in allowed_methods:
5656

57-
@router.post("/{add_or_id}", response_model=model.table)
57+
@router.post("/{add_or_id}", response_model=model.payload)
5858
async def add_or_update(
5959
add_or_id: str,
6060
body: model.payload,

fastapi-postgres/common/db_model/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ async def add_or_find_update_single(
118118
add_or_id: str | int,
119119
body: BaseModel | dict[str, Any],
120120
**kwargs: Any,
121-
) -> "cls.table":
121+
) -> BaseTable:
122122
user_auth = kwargs.get("user_auth")
123123

124124
if add_or_id != "add":
@@ -203,7 +203,7 @@ async def fetch_rows(
203203
_.model_dump(include_relations=filter_query.relation_model)
204204
for _ in results
205205
]
206-
if as_dict or filter_query.relation_model
206+
if as_dict
207207
else list(results)
208208
)
209209
except Exception as ex:

fastapi-postgres/common/enums/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Grade(EnumBase):
4040
F = "F"
4141
G = "G"
4242
H = "H"
43-
I = "I"
43+
I_ = "I"
4444
J = "J"
4545
K = "K"
4646
L = "L"

fastapi-postgres/common/serializers/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, List, Optional, Set, TypeAlias
1+
from typing import Any, TypeAlias
22

33
from pydantic import BaseModel
44
from pydantic import Field as PydanticField
@@ -15,7 +15,7 @@ def model_dump(
1515
*,
1616
include_relations: bool = False,
1717
max_depth: int = 1,
18-
_visited: Set[int] | None = None,
18+
_visited: set[int] | None = None,
1919
**kwargs: Any,
2020
) -> dict[str, Any]:
2121
base = super().model_dump(**kwargs)
@@ -72,7 +72,7 @@ def model_dump(
7272

7373

7474
class IdBaseTable(BaseTable):
75-
id: Optional[int] = Field(default=None, primary_key=True)
75+
id: int | None = Field(default=None, primary_key=True)
7676

7777
def __hash__(self):
7878
return hash(self.id)
@@ -93,9 +93,9 @@ class DBQuery(BaseModel):
9393

9494

9595
class FilterQuery(BaseModel):
96-
query: List[DBQuery] = []
96+
query: list[DBQuery] = Field(default_factory=list)
9797
relation_model: bool = False
98-
sort: Optional[str] = None
98+
sort: str | None = None
9999

100100

101101
class Pagination(BaseModel):

fastapi-postgres/common/serializers/payload.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import List
2-
31
from pydantic import BaseModel, Field
42

53
from common.enums import Grade
@@ -19,7 +17,7 @@ class StudentPayload(BaseModel):
1917

2018

2119
class FullStudentPayload(StudentPayload):
22-
assignments: List[AssignmentPayload] = []
20+
assignments: list[AssignmentPayload] = []
2321
id: int
2422

2523

fastapi-postgres/common/serializers/table_model.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import List, Optional
2-
31
from sqlmodel import Field, Relationship, String, UniqueConstraint
42

53
from common.enums import Grade
@@ -8,27 +6,34 @@
86

97
class Teacher(IdBaseTable, table=True):
108
__table_args__ = (UniqueConstraint("phone", "id", name="phone_id"),)
9+
1110
phone: float
12-
students: Optional[List["Student"]] = Relationship(
13-
sa_relationship_kwargs={"cascade": "all, delete"}, back_populates="teacher"
11+
12+
students: list["Student"] | None = Relationship(
13+
sa_relationship_kwargs={"cascade": "all, delete"},
14+
back_populates="teacher",
1415
)
1516

16-
assignments: Optional[List["Assignment"]] = Relationship(
17-
sa_relationship_kwargs={"cascade": "all, delete"}, back_populates="teacher"
17+
assignments: list["Assignment"] | None = Relationship(
18+
sa_relationship_kwargs={"cascade": "all, delete"},
19+
back_populates="teacher",
1820
)
1921

2022

2123
class Student(IdBaseTable, table=True):
2224
__table_args__ = (UniqueConstraint("name", "phone", name="name_phone"),)
25+
2326
teacher_id: int = Field(foreign_key="teacher.id")
2427
teacher: Teacher = Relationship(back_populates="students")
2528

2629
name: str
2730
grade: Grade = Field(sa_type=String, nullable=False)
2831

2932
phone: float
30-
assignments: Optional[List["Assignment"]] = Relationship(
31-
sa_relationship_kwargs={"cascade": "all, delete"}, back_populates="student"
33+
34+
assignments: list["Assignment"] | None = Relationship(
35+
sa_relationship_kwargs={"cascade": "all, delete"},
36+
back_populates="student",
3237
)
3338

3439

fastapi-postgres/common/utils/parse_obj.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime
2-
from typing import Dict, List, Union, get_type_hints
2+
from typing import Union, get_type_hints
33

44
from pydantic import BaseModel
55

@@ -11,8 +11,8 @@ class ParseObj:
1111
def set_elements_by_dict(
1212
cls,
1313
db_obj: BaseTable,
14-
new_obj: Union[BaseModel, BaseTable, Dict],
15-
exclude_items: List[str] = [],
14+
new_obj: Union[BaseModel, BaseTable, dict],
15+
exclude_items: list[str] = [],
1616
):
1717
def extract_items(obj):
1818
if hasattr(obj, "model_dump"):
@@ -30,15 +30,15 @@ def update_nested(target, updates):
3030
if k not in exclude_items:
3131
setattr(target, k, v)
3232

33-
def coerce_datetime_if_needed(field_name, value):
33+
def coerce_datetime_if_needed(field_name, _value):
3434
expected_types = get_type_hints(db_obj.__class__)
3535
if field_name in expected_types and expected_types[field_name] == datetime:
36-
if isinstance(value, str):
36+
if isinstance(_value, str):
3737
try:
38-
return datetime.fromisoformat(value)
38+
return datetime.fromisoformat(_value)
3939
except Exception:
40-
return value
41-
return value
40+
return _value
41+
return _value
4242

4343
items = extract_items(new_obj)
4444

fastapi-postgres/format.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
#!/bin/bash
2-
#it's not in the requirement file maybe you need to install it
2+
3+
# Development tools (not in requirements.txt):
4+
# pip install ruff isort black
5+
36
# Format Python code with black and sort imports with isort
47
echo "Running isort..."
58
isort .
69

710
echo "Running black..."
811
black .
12+
13+
echo "Running ruff (lint)..."
14+
ruff check . --fix

0 commit comments

Comments
 (0)