From b1b5b5ce681c544365414f8b2f08b5119c575023 Mon Sep 17 00:00:00 2001 From: grucshetskyaleksei Date: Wed, 20 Sep 2023 00:07:12 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=87=D0=B8=D0=B9=20Po?= =?UTF-8?q?stgres?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/fastapi_app/.env.example | 16 ++++++------- src/fastapi_app/docker-compose.dev.yml | 10 ++++---- src/fastapi_app/docker-compose.yml | 10 ++++---- src/fastapi_app/lib/api/models/mixins.py | 8 +++++-- src/fastapi_app/lib/api/services/token.py | 11 +++++---- src/fastapi_app/lib/app/settings.py | 11 +++++---- src/fastapi_app/lib/db/postgres.py | 28 +++++++++++++++-------- 7 files changed, 56 insertions(+), 38 deletions(-) diff --git a/src/fastapi_app/.env.example b/src/fastapi_app/.env.example index 550634c..d557292 100644 --- a/src/fastapi_app/.env.example +++ b/src/fastapi_app/.env.example @@ -1,10 +1,10 @@ -db_host=db -db_port=5432 -db_user=user -db_password=Qwe123 -db_name=notification_admin +DB_HOST=db +DB_PORT=5432 +DB_USER=user +DB_PASSWORD=Qwe123 +DB_NAME=api_db -server_host=0.0.0.0 -server_port=8000 +SERVER_HOST=0.0.0.0 +SERVER_PORT=8000 -jwt_secret_key=v9LctjUWwol4XbvczPiLFMDtZ8aal7mm +JWT_SECRET_KEY=v9LctjUWwol4XbvczPiLFMDtZ8aal7mm diff --git a/src/fastapi_app/docker-compose.dev.yml b/src/fastapi_app/docker-compose.dev.yml index 283ac0b..6ae7ddb 100644 --- a/src/fastapi_app/docker-compose.dev.yml +++ b/src/fastapi_app/docker-compose.dev.yml @@ -4,13 +4,13 @@ services: db: image: postgres:15.2 environment: - POSTGRES_USER: ${db_user} - POSTGRES_PASSWORD: ${db_password} - POSTGRES_DB: ${db_name} + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} env_file: - .env ports: - - "${db_port}:{db_port}" + - "${DB_PORT}:${DB_PORT}" volumes: - postgres_data:/var/lib/postgresql/data/ restart: always @@ -25,7 +25,7 @@ services: restart: always entrypoint: ["/opt/app/entrypoint.sh"] ports: - - "${server_port}:{server_port}" + - "${SERVER_PORT}:${SERVER_PORT}" depends_on: - db env_file: diff --git a/src/fastapi_app/docker-compose.yml b/src/fastapi_app/docker-compose.yml index 88a2117..c338168 100644 --- a/src/fastapi_app/docker-compose.yml +++ b/src/fastapi_app/docker-compose.yml @@ -4,13 +4,13 @@ services: db: image: postgres:15.2 environment: - POSTGRES_USER: ${db_user} - POSTGRES_PASSWORD: ${db_password} - POSTGRES_DB: ${db_name} + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} env_file: - .env ports: - - "127.0.0.1:${db_port}:{db_port}" + - "127.0.0.1:${DB_PORT}:${DB_PORT}" volumes: - postgres_data:/var/lib/postgresql/data/ restart: always @@ -20,7 +20,7 @@ services: api: build: context: . - container_name: fastapi_app + container_name: api image: fastapi_app restart: always entrypoint: ["/opt/app/entrypoint.sh"] diff --git a/src/fastapi_app/lib/api/models/mixins.py b/src/fastapi_app/lib/api/models/mixins.py index 3380a9f..e33b305 100644 --- a/src/fastapi_app/lib/api/models/mixins.py +++ b/src/fastapi_app/lib/api/models/mixins.py @@ -18,8 +18,12 @@ class BaseMixin: @declared_attr def created_at(cls): - return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now()) + return sqlalchemy.Column( + sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now() + ) @declared_attr def updated_at(cls): - return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now()) + return sqlalchemy.Column( + sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now() + ) diff --git a/src/fastapi_app/lib/api/services/token.py b/src/fastapi_app/lib/api/services/token.py index 5d0dedb..b2277c0 100644 --- a/src/fastapi_app/lib/api/services/token.py +++ b/src/fastapi_app/lib/api/services/token.py @@ -1,10 +1,9 @@ -import fastapi - from jose import JWTError, jwt -from pydantic import ValidationError - from lib.api import schemas as app_schemas from lib.app import settings as app_settings +from pydantic import ValidationError + +import fastapi app = fastapi.FastAPI() settings = app_settings.get_settings() @@ -13,7 +12,9 @@ security = fastapi.security.HTTPBearer() def get_token_data( - authorization: fastapi.security.HTTPAuthorizationCredentials = fastapi.Security(security), + authorization: fastapi.security.HTTPAuthorizationCredentials = fastapi.Security( + security + ), ) -> app_schemas.entity.Token: token = authorization.credentials try: diff --git a/src/fastapi_app/lib/app/settings.py b/src/fastapi_app/lib/app/settings.py index 3edbe95..dc91b87 100644 --- a/src/fastapi_app/lib/app/settings.py +++ b/src/fastapi_app/lib/app/settings.py @@ -1,10 +1,7 @@ import functools import pydantic_settings -from dotenv import load_dotenv -from pydantic import Field - -load_dotenv(".env.dev") +from pydantic import Field, field_validator class DbSettings(pydantic_settings.BaseSettings): @@ -25,11 +22,17 @@ class ApiSettings(pydantic_settings.BaseSettings): class Settings(pydantic_settings.BaseSettings): + debug: str = "false" db: DbSettings = Field(default_factory=DbSettings) api: ApiSettings = Field(default_factory=ApiSettings) jwt_secret_key: str + @field_validator("debug") + @classmethod + def validate_debug(cls, v: str) -> bool: + return v.lower() == "true" + @functools.lru_cache def get_settings() -> Settings: diff --git a/src/fastapi_app/lib/db/postgres.py b/src/fastapi_app/lib/db/postgres.py index 1ad8e1b..9ad37d9 100644 --- a/src/fastapi_app/lib/db/postgres.py +++ b/src/fastapi_app/lib/db/postgres.py @@ -15,17 +15,27 @@ class Base(DeclarativeBase): # Создаём движок # Настройки подключения к БД передаём из переменных окружения, которые заранее загружены в файл настроек +class AsyncDB: + def __init__(self): + self.database_dsn = ( + f"postgresql+asyncpg://{settings.db.user}:{settings.db.password}" + f"@{settings.db.host}:{settings.db.port}/{settings.db.name}" + ) + self.engine = create_async_engine( + self.database_dsn, echo=settings.debug, future=True + ) + self.async_session = async_sessionmaker( + self.engine, class_=AsyncSession, expire_on_commit=False + ) -database_dsn = ( - f"postgresql+asyncpg://{settings.db.user}:{settings.db.password}" - f"@{settings.db.host}:{settings.db.port}/{settings.db.name}" -) -engine = create_async_engine(database_dsn, echo=True, future=True) - -async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) +db = AsyncDB() async def get_session() -> typing.AsyncGenerator[AsyncSession, typing.Any]: - async with async_session() as session: - yield session + async with db.async_session() as session: + try: + yield session + except Exception: + await session.rollback() + raise