From eb1e690fa408644ffbc6da314c57e08b244f57a6 Mon Sep 17 00:00:00 2001 From: jonra1993 Date: Sat, 26 Feb 2022 11:07:35 -0500 Subject: [PATCH 1/4] add settings and db sqlmodel libs --- docker-compose.yml | 6 +++++- project/app/db.py | 15 ++++++--------- project/app/main.py | 4 ++-- project/app/models.py | 2 +- project/app/settings.py | 30 ++++++++++++++++++++++++++++++ project/migrations/env.py | 26 +++++++++++--------------- 6 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 project/app/settings.py diff --git a/docker-compose.yml b/docker-compose.yml index 8be7def..518cef5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,7 +10,11 @@ services: ports: - 8004:8000 environment: - - DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/foo + - DATABASE_HOST=db + - DATABASE_USER=postgres + - DATABASE_PASSWORD=postgres + - DATABASE_NAME=foo + - DATABASE_PORT=5432 depends_on: - db diff --git a/project/app/db.py b/project/app/db.py index 48f9665..e3ee548 100644 --- a/project/app/db.py +++ b/project/app/db.py @@ -1,15 +1,12 @@ -import os - -from sqlmodel import SQLModel - -from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine +from sqlmodel import SQLModel, create_engine from sqlalchemy.orm import sessionmaker +from sqlmodel.ext.asyncio.session import AsyncSession, AsyncEngine +from app.settings import Settings +settings = Settings() -DATABASE_URL = os.environ.get("DATABASE_URL") - -engine = create_async_engine(DATABASE_URL, echo=True, future=True) - +print('settings.ASYNC_DATABASE_URI', settings.ASYNC_DATABASE_URI) +engine = AsyncEngine(create_engine(settings.ASYNC_DATABASE_URI, echo=True, future=True)) async def init_db(): async with engine.begin() as conn: diff --git a/project/app/main.py b/project/app/main.py index 2b24454..cf69730 100644 --- a/project/app/main.py +++ b/project/app/main.py @@ -1,6 +1,6 @@ from fastapi import Depends, FastAPI -from sqlalchemy.future import select -from sqlalchemy.ext.asyncio import AsyncSession +from sqlmodel import select +from sqlmodel.ext.asyncio.session import AsyncSession from app.db import get_session from app.models import Song, SongCreate diff --git a/project/app/models.py b/project/app/models.py index 0f2d7cd..17bbadb 100644 --- a/project/app/models.py +++ b/project/app/models.py @@ -10,7 +10,7 @@ class SongBase(SQLModel): class Song(SongBase, table=True): - id: int = Field(default=None, primary_key=True) + id: int = Field(default=None, nullable=False, primary_key=True) class SongCreate(SongBase): diff --git a/project/app/settings.py b/project/app/settings.py new file mode 100644 index 0000000..bfb7e8e --- /dev/null +++ b/project/app/settings.py @@ -0,0 +1,30 @@ +import os +from pydantic import BaseSettings, PostgresDsn, validator +from typing import Optional, Dict, Any, Union + +class Settings(BaseSettings): + DATABASE_USER: str = os.environ.get("DATABASE_USER") + DATABASE_PASSWORD: str = os.environ.get("DATABASE_PASSWORD") + DATABASE_HOST: str = os.environ.get("DATABASE_HOST") + DATABASE_PORT: Union[int, str] = os.environ.get("DATABASE_PORT") + DATABASE_NAME: str = os.environ.get("DATABASE_NAME") + ASYNC_DATABASE_URI: Optional[ + Any + ] = f"postgresql+asyncpg://{DATABASE_USER}:{DATABASE_PASSWORD}@{DATABASE_HOST}:{DATABASE_PORT}/{DATABASE_NAME}" + + @validator("ASYNC_DATABASE_URI", pre=True) + def assemble_db_connection(cls, v: Optional[str], values: Dict[str, Any]) -> Any: + if isinstance(v, str): + return v + return PostgresDsn.build( + scheme="postgresql+asyncpg", + user=values.get("DATABASE_USER"), + password=values.get("DATABASE_PASSWORD"), + host=values.get("DATABASE_HOST"), + port=values.get("DATABASE_PORT"), + path=f"/{values.get('DATABASE_NAME') or ''}", + ) + + class Config: + case_sensitive = True + env_file = os.path.expanduser("~/.env") diff --git a/project/migrations/env.py b/project/migrations/env.py index 3180608..b2849b7 100644 --- a/project/migrations/env.py +++ b/project/migrations/env.py @@ -1,15 +1,18 @@ import asyncio from logging.config import fileConfig -from sqlalchemy import engine_from_config -from sqlalchemy import pool -from sqlalchemy.ext.asyncio import AsyncEngine -from sqlmodel import SQLModel +from sqlmodel import SQLModel, create_engine +from sqlmodel.ext.asyncio.session import AsyncEngine from alembic import context -from app.models import Song +from app.models import Song # All models that needs to be migrated should be added +from app.settings import Settings +print('settings.ASYNC_DATABASE_URIaa') + +settings = Settings() +print('settings.ASYNC_DATABASE_URI', settings.ASYNC_DATABASE_URI) # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config @@ -41,8 +44,8 @@ def run_migrations_offline(): Calls to context.execute() here emit the given string to the script output. - """ - url = config.get_main_option("sqlalchemy.url") + """ + url = settings.ASYNC_DATABASE_URI context.configure( url=url, target_metadata=target_metadata, @@ -68,14 +71,7 @@ async def run_migrations_online(): and associate a connection with the context. """ - connectable = AsyncEngine( - engine_from_config( - config.get_section(config.config_ini_section), - prefix="sqlalchemy.", - poolclass=pool.NullPool, - future=True, - ) - ) + connectable = AsyncEngine(create_engine(settings.ASYNC_DATABASE_URI, echo=True, future=True)) async with connectable.connect() as connection: await connection.run_sync(do_run_migrations) From 2e5adc1d8c36db5f4adfdf5da93efabb70993645 Mon Sep 17 00:00:00 2001 From: jonra1993 Date: Sat, 26 Feb 2022 11:11:21 -0500 Subject: [PATCH 2/4] Update readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index e5f3bfa..c70c110 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,13 @@ $ docker-compose up -d --build $ docker-compose exec web alembic upgrade head ``` +## Want to make a migration? + +```sh +$ docker-compose exec web alembic revision --autogenerate +$ docker-compose exec web alembic upgrade head +``` + Sanity check: [http://localhost:8004/ping](http://localhost:8004/ping) Add a song: From 15c7651052ddc59cc2095c472459fb4b5814ead8 Mon Sep 17 00:00:00 2001 From: jonra1993 Date: Sat, 26 Feb 2022 11:12:46 -0500 Subject: [PATCH 3/4] Remove prints --- project/app/db.py | 1 - 1 file changed, 1 deletion(-) diff --git a/project/app/db.py b/project/app/db.py index e3ee548..f08a52c 100644 --- a/project/app/db.py +++ b/project/app/db.py @@ -5,7 +5,6 @@ settings = Settings() -print('settings.ASYNC_DATABASE_URI', settings.ASYNC_DATABASE_URI) engine = AsyncEngine(create_engine(settings.ASYNC_DATABASE_URI, echo=True, future=True)) async def init_db(): From dea835b0b2640e275a4a0d581d5f42b448ab8850 Mon Sep 17 00:00:00 2001 From: jonra1993 Date: Sat, 26 Feb 2022 11:12:52 -0500 Subject: [PATCH 4/4] Remve prints --- project/migrations/env.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/project/migrations/env.py b/project/migrations/env.py index b2849b7..51e1f41 100644 --- a/project/migrations/env.py +++ b/project/migrations/env.py @@ -9,10 +9,8 @@ from app.models import Song # All models that needs to be migrated should be added from app.settings import Settings -print('settings.ASYNC_DATABASE_URIaa') settings = Settings() -print('settings.ASYNC_DATABASE_URI', settings.ASYNC_DATABASE_URI) # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config