Skip to content

Commit 84667f7

Browse files
committed
feat: generate model classes from database using sqlacodegen
Reverse engineered model classes from the existing database schema using sqlacodegen. Use this when the database
1 parent 0e33d6b commit 84667f7

File tree

6 files changed

+1040
-874
lines changed

6 files changed

+1040
-874
lines changed

.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,6 @@ SENTRY_DSN=
4343
# Configure these with your own Docker registry images
4444
DOCKER_IMAGE_BACKEND=backend
4545
DOCKER_IMAGE_FRONTEND=frontend
46+
47+
# DSN for database reverse engineering
48+
DATABASE_SOURCE_DSN=postgresql+psycopg2://<USER>:<PASSWORD>@<IP>:<PORT>/<DB_NAME>

backend/app/generated_sqlmodels.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from typing import Optional
2+
import uuid
3+
4+
from sqlalchemy import Boolean, Column, ForeignKeyConstraint, Index, PrimaryKeyConstraint, String, Uuid
5+
from sqlmodel import Field, Relationship, SQLModel
6+
7+
class Category(SQLModel, table=True):
8+
__table_args__ = (
9+
PrimaryKeyConstraint('id', name='category_pkey'),
10+
)
11+
12+
name: str = Field(sa_column=Column('name', String(100), nullable=False))
13+
id: uuid.UUID = Field(sa_column=Column('id', Uuid, primary_key=True))
14+
created_at: str = Field(sa_column=Column('created_at', String, nullable=False))
15+
description: Optional[str] = Field(default=None, sa_column=Column('description', String(500)))
16+
17+
18+
class User(SQLModel, table=True):
19+
__table_args__ = (
20+
PrimaryKeyConstraint('id', name='user_pkey'),
21+
Index('ix_user_email', 'email', unique=True)
22+
)
23+
24+
email: str = Field(sa_column=Column('email', String(255), nullable=False))
25+
is_active: bool = Field(sa_column=Column('is_active', Boolean, nullable=False))
26+
is_superuser: bool = Field(sa_column=Column('is_superuser', Boolean, nullable=False))
27+
hashed_password: str = Field(sa_column=Column('hashed_password', String, nullable=False))
28+
id: uuid.UUID = Field(sa_column=Column('id', Uuid, primary_key=True))
29+
full_name: Optional[str] = Field(default=None, sa_column=Column('full_name', String(255)))
30+
31+
item: list['Item'] = Relationship(back_populates='owner')
32+
33+
34+
class Item(SQLModel, table=True):
35+
__table_args__ = (
36+
ForeignKeyConstraint(['owner_id'], ['user.id'], ondelete='CASCADE', name='item_owner_id_fkey'),
37+
PrimaryKeyConstraint('id', name='item_pkey')
38+
)
39+
40+
title: str = Field(sa_column=Column('title', String(255), nullable=False))
41+
id: uuid.UUID = Field(sa_column=Column('id', Uuid, primary_key=True))
42+
owner_id: uuid.UUID = Field(sa_column=Column('owner_id', Uuid, nullable=False))
43+
description: Optional[str] = Field(default=None, sa_column=Column('description', String(255)))
44+
45+
owner: Optional['User'] = Relationship(back_populates='item')

backend/pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ dependencies = [
2121
"pydantic-settings<3.0.0,>=2.2.1",
2222
"sentry-sdk[fastapi]<2.0.0,>=1.40.6",
2323
"pyjwt<3.0.0,>=2.8.0",
24+
"sqlacodegen>=3.1.1",
25+
"psycopg2>=2.9.10",
2426
]
2527

2628
[tool.uv]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# PowerShell version of SQLModel generation script
2+
3+
# Simple SQLModel generation script
4+
# Read database configuration from .env file
5+
6+
# Stop on error
7+
$ErrorActionPreference = "Stop"
8+
9+
Write-Host "Reading configuration from .env file..." -ForegroundColor Blue
10+
11+
# Read .env file
12+
$envFile = "../../.env"
13+
if (-not (Test-Path $envFile)) {
14+
Write-Error ".env file not found at $envFile"
15+
exit 1
16+
}
17+
18+
# Parse .env file
19+
$envVars = @{}
20+
Get-Content $envFile | ForEach-Object {
21+
if ($_ -match '^([^#][^=]*?)=(.*)$') {
22+
$envVars[$matches[1]] = $matches[2]
23+
}
24+
}
25+
26+
if (-not $envVars.ContainsKey('DATABASE_SOURCE_DSN')) {
27+
Write-Error "DATABASE_SOURCE_DSN not found in .env file"
28+
exit 1
29+
}
30+
31+
$databaseDsn = $envVars['DATABASE_SOURCE_DSN']
32+
33+
Write-Host "Executing sqlacodegen..." -ForegroundColor Blue
34+
Write-Host "Command: uv run sqlacodegen --generator sqlmodels `"$databaseDsn`" --outfile ../app/generated_sqlmodels.py" -ForegroundColor Gray
35+
36+
# Execute sqlacodegen
37+
uv run sqlacodegen --generator sqlmodels "$databaseDsn" --outfile ../app/generated_sqlmodels.py
38+
39+
if ($LASTEXITCODE -eq 0) {
40+
Write-Host "SQLModel code generated successfully: ../app/generated_sqlmodels.py" -ForegroundColor Green
41+
} else {
42+
Write-Error "Failed to generate SQLModel code"
43+
exit 1
44+
}

backend/scripts/generate_models.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#! /usr/bin/env bash
2+
3+
# Simple SQLModel generation script
4+
# Read database configuration from .env file
5+
6+
set -e
7+
set -x
8+
9+
# Read .env file
10+
source ../../.env
11+
12+
# Execute sqlacodegen
13+
sqlacodegen --generator sqlmodels "$DATABASE_SOURCE_DSN" --outfile ../app/generated_sqlmodels.py
14+
15+
echo "SQLModel code generated successfully: ../app/generated_sqlmodels.py"

0 commit comments

Comments
 (0)