From f14c58638945343cdf08f04886a8ef4347f0bd5f Mon Sep 17 00:00:00 2001 From: grillazz Date: Tue, 29 Jul 2025 17:26:37 +0200 Subject: [PATCH] add json filed example --- Makefile | 2 +- ...250729_1521_d021bd4763a5_add_json_chaos.py | 37 +++++++++++++++++++ app/api/stuff.py | 13 ++++++- app/models/base.py | 3 +- app/models/stuff.py | 12 ++++++ app/schemas/stuff.py | 7 +++- compose.yml | 1 + 7 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 alembic/versions/20250729_1521_d021bd4763a5_add_json_chaos.py diff --git a/Makefile b/Makefile index 6bafa7d..3d6ef3a 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ docker-apply-db-migrations: ## apply alembic migrations to database/schema docker compose run --rm app alembic upgrade head .PHONY: docker-create-db-migration -docker-create-db-migration: ## Create new alembic database migration aka database revision. +docker-create-db-migration: ## Create new alembic database migration aka database revision. Example: make docker-create-db-migration msg="add users table" docker compose up -d db | true docker compose run --no-deps app alembic revision --autogenerate -m "$(msg)" diff --git a/alembic/versions/20250729_1521_d021bd4763a5_add_json_chaos.py b/alembic/versions/20250729_1521_d021bd4763a5_add_json_chaos.py new file mode 100644 index 0000000..a629c14 --- /dev/null +++ b/alembic/versions/20250729_1521_d021bd4763a5_add_json_chaos.py @@ -0,0 +1,37 @@ +"""add json chaos + +Revision ID: d021bd4763a5 +Revises: 0c69050b5a3e +Create Date: 2025-07-29 15:21:19.415583 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'd021bd4763a5' +down_revision = '0c69050b5a3e' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('random_stuff', + sa.Column('id', sa.UUID(), nullable=False), + sa.Column('chaos', postgresql.JSON(astext_type=sa.Text()), nullable=False), + sa.PrimaryKeyConstraint('id'), + schema='happy_hog' + ) + op.create_unique_constraint(None, 'nonsense', ['name'], schema='happy_hog') + op.create_unique_constraint(None, 'stuff', ['name'], schema='happy_hog') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'stuff', schema='happy_hog', type_='unique') + op.drop_constraint(None, 'nonsense', schema='happy_hog', type_='unique') + op.drop_table('random_stuff', schema='happy_hog') + # ### end Alembic commands ### diff --git a/app/api/stuff.py b/app/api/stuff.py index 379b661..baacee7 100644 --- a/app/api/stuff.py +++ b/app/api/stuff.py @@ -4,14 +4,23 @@ from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db -from app.models.stuff import Stuff -from app.schemas.stuff import StuffResponse, StuffSchema +from app.models.stuff import Stuff, RandomStuff +from app.schemas.stuff import StuffResponse, StuffSchema, RandomStuff as RandomStuffSchema logger = AppStructLogger().get_logger() router = APIRouter(prefix="/v1/stuff") +@router.post("/random", status_code=status.HTTP_201_CREATED) +async def create_random_stuff( + payload: RandomStuffSchema, db_session: AsyncSession = Depends(get_db) +) -> dict[str, str]: + random_stuff = RandomStuff(**payload.model_dump()) + await random_stuff.save(db_session) + return {"id": str(random_stuff.id)} + + @router.post("/add_many", status_code=status.HTTP_201_CREATED) async def create_multi_stuff( payload: list[StuffSchema], db_session: AsyncSession = Depends(get_db) diff --git a/app/models/base.py b/app/models/base.py index 5e059df..77575f7 100644 --- a/app/models/base.py +++ b/app/models/base.py @@ -27,7 +27,8 @@ class Base(DeclarativeBase): """ try: db_session.add(self) - return await db_session.commit() + await db_session.commit() + return await db_session.refresh(self) except SQLAlchemyError as ex: await logger.aerror(f"Error inserting instance of {self}: {repr(ex)}") raise HTTPException( diff --git a/app/models/stuff.py b/app/models/stuff.py index 248d7e3..683732e 100644 --- a/app/models/stuff.py +++ b/app/models/stuff.py @@ -9,6 +9,18 @@ from app.models.base import Base from app.models.nonsense import Nonsense from app.utils.decorators import compile_sql_or_scalar +from sqlalchemy.dialects.postgresql import JSON + + +class RandomStuff(Base): + __tablename__ = "random_stuff" + __table_args__ = ({"schema": "happy_hog"},) + + id: Mapped[uuid.UUID] = mapped_column( + UUID(as_uuid=True), default=uuid.uuid4, primary_key=True + ) + chaos: Mapped[dict] = mapped_column(JSON) + class Stuff(Base): __tablename__ = "stuff" diff --git a/app/schemas/stuff.py b/app/schemas/stuff.py index d5703b2..258cc87 100644 --- a/app/schemas/stuff.py +++ b/app/schemas/stuff.py @@ -1,10 +1,13 @@ from uuid import UUID -from pydantic import BaseModel, ConfigDict, Field - +from pydantic import BaseModel, ConfigDict, Field, Json +from typing import Any config = ConfigDict(from_attributes=True) +class RandomStuff(BaseModel): + chaos: dict[str, Any] = Field(..., description="JSON data for chaos field") + class StuffSchema(BaseModel): name: str = Field( title="", diff --git a/compose.yml b/compose.yml index 293db32..d9fdc99 100644 --- a/compose.yml +++ b/compose.yml @@ -18,6 +18,7 @@ services: - ./app:/panettone/app - ./tests:/panettone/tests - ./templates:/panettone/templates + - ./alembic:/panettone/alembic ports: - "8080:8080" depends_on: