From c2385514677aeca7a3d6a0d8a1a7d43dc9cd5194 Mon Sep 17 00:00:00 2001 From: Jack Case Date: Fri, 17 Oct 2025 20:13:02 +0000 Subject: [PATCH] initial alembic revision followed article here for guidance: https://arunanshub.hashnode.dev/using-sqlmodel-with-alembic#heading-sql-constraint-naming-convention mirrored on my readeck: https://readeck.yuno.jack-case.pro/bookmarks/9ay79PHux348cgQBnA86UC --- alembic.ini | 4 +- slopserver/__init__.py | 0 {alembic => slopserver/alembic}/README | 0 {alembic => slopserver/alembic}/env.py | 6 ++- .../alembic}/script.py.mako | 1 + .../alembic/versions/72dcd047d7bf_initial.py | 47 +++++++++++++++++++ slopserver/models.py | 25 ++++++++++ 7 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 slopserver/__init__.py rename {alembic => slopserver/alembic}/README (100%) rename {alembic => slopserver/alembic}/env.py (94%) rename {alembic => slopserver/alembic}/script.py.mako (96%) create mode 100644 slopserver/alembic/versions/72dcd047d7bf_initial.py create mode 100644 slopserver/models.py diff --git a/alembic.ini b/alembic.ini index 1b03b05..56338a5 100644 --- a/alembic.ini +++ b/alembic.ini @@ -5,7 +5,7 @@ # this is typically a path given in POSIX (e.g. forward slashes) # format, relative to the token %(here)s which refers to the location of this # ini file -script_location = %(here)s/alembic +script_location = %(here)s/slopserver/alembic # template used to generate migration file names; The default value is %%(rev)s_%%(slug)s # Uncomment the line below if you want the files to be prepended with date and time @@ -84,7 +84,7 @@ path_separator = os # database URL. This is consumed by the user-maintained env.py script only. # other means of configuring database URLs may be customized within the env.py # file. -sqlalchemy.url = driver://user:pass@localhost/dbname +sqlalchemy.url = postgresql+psycopg://slop-farmer@192.168.1.163/slop-farmer [post_write_hooks] diff --git a/slopserver/__init__.py b/slopserver/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/alembic/README b/slopserver/alembic/README similarity index 100% rename from alembic/README rename to slopserver/alembic/README diff --git a/alembic/env.py b/slopserver/alembic/env.py similarity index 94% rename from alembic/env.py rename to slopserver/alembic/env.py index 36112a3..7cda2fb 100644 --- a/alembic/env.py +++ b/slopserver/alembic/env.py @@ -18,7 +18,8 @@ if config.config_file_name is not None: # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata -target_metadata = None +from slopserver.models import metadata +target_metadata = metadata # other values from the config, defined by the needs of env.py, # can be acquired: @@ -65,7 +66,8 @@ def run_migrations_online() -> None: with connectable.connect() as connection: context.configure( - connection=connection, target_metadata=target_metadata + connection=connection, target_metadata=target_metadata, + user_module_prefix="sqlmodel.sql.sqltypes." ) with context.begin_transaction(): diff --git a/alembic/script.py.mako b/slopserver/alembic/script.py.mako similarity index 96% rename from alembic/script.py.mako rename to slopserver/alembic/script.py.mako index 1101630..6fb73b8 100644 --- a/alembic/script.py.mako +++ b/slopserver/alembic/script.py.mako @@ -9,6 +9,7 @@ from typing import Sequence, Union from alembic import op import sqlalchemy as sa +import sqlmodel.sql.sqltypes ${imports if imports else ""} # revision identifiers, used by Alembic. diff --git a/slopserver/alembic/versions/72dcd047d7bf_initial.py b/slopserver/alembic/versions/72dcd047d7bf_initial.py new file mode 100644 index 0000000..fb538cf --- /dev/null +++ b/slopserver/alembic/versions/72dcd047d7bf_initial.py @@ -0,0 +1,47 @@ +"""initial + +Revision ID: 72dcd047d7bf +Revises: +Create Date: 2025-10-17 20:10:04.230321 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa +import sqlmodel.sql.sqltypes + + +# revision identifiers, used by Alembic. +revision: str = '72dcd047d7bf' +down_revision: Union[str, Sequence[str], None] = None +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('domain', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('domain_name', sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.PrimaryKeyConstraint('id', name=op.f('pk_domain')) + ) + op.create_index(op.f('ix_domain_domain_name'), 'domain', ['domain_name'], unique=True) + op.create_table('path', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('path', sqlmodel.sql.sqltypes.AutoString(), nullable=False), + sa.Column('domain_id', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['domain_id'], ['domain.id'], name=op.f('fk_path_domain_id_domain')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_path')) + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('path') + op.drop_index(op.f('ix_domain_domain_name'), table_name='domain') + op.drop_table('domain') + # ### end Alembic commands ### diff --git a/slopserver/models.py b/slopserver/models.py new file mode 100644 index 0000000..126ae7c --- /dev/null +++ b/slopserver/models.py @@ -0,0 +1,25 @@ +from sqlmodel import Field, SQLModel, create_engine, Relationship + +NAMING_CONVENTION = { + "ix": "ix_%(column_0_label)s", + "uq": "uq_%(table_name)s_%(column_0_name)s", + "ck": "ck_%(table_name)s_%(constraint_name)s", + "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", + "pk": "pk_%(table_name)s", +} + +metadata = SQLModel.metadata +metadata.naming_convention = NAMING_CONVENTION + +class Domain(SQLModel, table=True): + id: int | None = Field(default=None, primary_key=True) + domain_name: str = Field(index=True, unique=True) + + paths: list["Path"] = Relationship(back_populates="domain") + +class Path(SQLModel, table=True): + id: int | None = Field(default=None, primary_key=True) + path: str + + domain_id: int = Field(foreign_key="domain.id") + domain: Domain = Relationship(back_populates="paths") \ No newline at end of file