Skip to content

Commit 11d28c3

Browse files
authored
Merge pull request #4 from rrad0812/develop
Dodata uputstva
2 parents 7ede039 + 95f5673 commit 11d28c3

File tree

2 files changed

+432
-0
lines changed

2 files changed

+432
-0
lines changed
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
2+
# Admin metadata exporter
3+
4+
Izvoz `admin.sqlite` meta-podataka u `SQLAlchemy` ORM klase. Svaka `SYS_` tabela iz baze dobija jednu `SQLAlchemy` klasu u posebnom `.py` fajlu unutar direktorijuma `models/`.
5+
6+
## Implementacija `admin.sqlite_exporter.py`
7+
8+
```py
9+
import os
10+
import sqlite3
11+
12+
OUTPUT_DIR = "models"
13+
14+
def ensure_dir(path):
15+
if not os.path.exists(path):
16+
os.makedirs(path)
17+
18+
def map_sqlite_type(sqlite_type: str):
19+
if not sqlite_type:
20+
return "String"
21+
t = sqlite_type.upper()
22+
if "INT" in t:
23+
return "Integer"
24+
if "CHAR" in t or "CLOB" in t or "TEXT" in t:
25+
return "String"
26+
if "BLOB" in t:
27+
return "LargeBinary"
28+
if "REAL" in t or "FLOA" in t or "DOUB" in t:
29+
return "Float"
30+
if "DATE" in t or "TIME" in t:
31+
return "DateTime"
32+
return "String"
33+
34+
def export_sys_models(db_path="admin.sqlite"):
35+
ensure_dir(OUTPUT_DIR)
36+
conn = sqlite3.connect(db_path)
37+
cur = conn.cursor()
38+
39+
# Sve SYS_ tabele iz admin.sqlite baze podataka
40+
cur.execute("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'SYS_%' ORDER BY name")
41+
tables = [r[0] for r in cur.fetchall()]
42+
43+
generated = []
44+
45+
for table_name in tables:
46+
cur.execute(f"PRAGMA table_info({table_name})")
47+
columns = cur.fetchall()
48+
if not columns:
49+
continue
50+
51+
class_name = "".join([w.capitalize() for w in table_name.lower().split("_")])
52+
generated.append((table_name, class_name))
53+
54+
lines = [
55+
"from sqlalchemy import String, Integer, Float, LargeBinary, DateTime, Boolean, Text",
56+
"from sqlalchemy.orm import Mapped, mapped_column",
57+
"from . import Base",
58+
"",
59+
f"class {class_name}(Base):",
60+
f" __tablename__ = '{table_name}'",
61+
"",
62+
]
63+
64+
for cid, name, col_type, notnull, default_value, pk in columns:
65+
sa_type = map_sqlite_type(col_type)
66+
pk_flag = ", primary_key=True" if pk else ""
67+
nullable = "" if notnull else ", nullable=True"
68+
default = f", default={default_value}" if default_value else ""
69+
lines.append(f" {name}: Mapped[{sa_type}] = mapped_column({sa_type}{pk_flag}{nullable}{default})")
70+
71+
lines.append("")
72+
lines.append(" def __repr__(self):")
73+
lines.append(f" return f\"<{class_name}(id={{getattr(self, 'ID', '?')}})>\"")
74+
lines.append("")
75+
76+
out_path = os.path.join(OUTPUT_DIR, f"{table_name.lower()}.py")
77+
with open(out_path, "w", encoding="utf-8") as f:
78+
f.write("\n".join(lines))
79+
print(f"Generisano: {out_path}")
80+
81+
# --- automatski __init__.py ---
82+
init_lines = [
83+
"# Auto-generated: Import All SYS_* Models",
84+
"from sqlalchemy.orm import DeclarativeBase",
85+
"",
86+
"class Base(DeclarativeBase):",
87+
" pass",
88+
"",
89+
]
90+
for table_name, class_name in generated:
91+
init_lines.append(f"from .{table_name.lower()} import {class_name}")
92+
init_lines.append("")
93+
init_lines.append("__all__ = [")
94+
for _, class_name in generated:
95+
init_lines.append(f" '{class_name}',")
96+
init_lines.append("]")
97+
init_lines.append("")
98+
99+
init_path = os.path.join(OUTPUT_DIR, "__init__.py")
100+
with open(init_path, "w", encoding="utf-8") as f:
101+
f.write("\n".join(init_lines))
102+
103+
conn.close()
104+
print("\n✅ Gotovo! Sve SYS_* ORM klase koriste zajednički Base iz models/__init__.py.")
105+
106+
if __name__ == "__main__":
107+
export_sys_models("admin.sqlite")
108+
```
109+
110+
### Primer generisanog fajla
111+
112+
`models/sys_items.py` nakon izvoza izgleda ovako:
113+
114+
```py
115+
from sqlalchemy import String, Integer, Float, LargeBinary, DateTime, Boolean, Text
116+
from sqlalchemy.orm import Mapped, mapped_column
117+
from . import Base
118+
119+
120+
class SysItems(Base):
121+
__tablename__ = 'SYS_ITEMS'
122+
123+
ID: Mapped[Integer] = mapped_column(Integer, primary_key=True)
124+
DELETED: Mapped[Integer] = mapped_column(Integer)
125+
PARENT: Mapped[Integer] = mapped_column(Integer)
126+
TASK_ID: Mapped[Integer] = mapped_column(Integer)
127+
F_NAME: Mapped[String] = mapped_column(String)
128+
129+
def __repr__(self):
130+
return f"<SysItems(id={getattr(self, 'ID', '?')})>"
131+
```
132+
133+
## Loader/tester za proveru ORM modela
134+
135+
```py
136+
from sqlalchemy import create_engine, inspect, select
137+
from sqlalchemy.orm import Session
138+
from models import Base
139+
140+
DB_PATH = "admin.sqlite"
141+
142+
engine = create_engine(f"sqlite:///{DB_PATH}", echo=False, future=True)
143+
144+
def main():
145+
print("Povezujem se na:", DB_PATH)
146+
Base.metadata.create_all(engine)
147+
148+
inspector = inspect(engine)
149+
tables = inspector.get_table_names()
150+
151+
print("\n📋 Pronađene tabele u bazi:")
152+
for t in tables:
153+
print(f"{t}")
154+
155+
with Session(engine) as session:
156+
print("\n🔍 Brz pregled SYS_ tabela:")
157+
for cls in Base.registry.mappers:
158+
model = cls.class_
159+
table_name = model.__tablename__
160+
try:
161+
count = session.execute(select(model)).fetchall()
162+
print(f" {table_name:<25}{len(count)} redova")
163+
except Exception as e:
164+
print(f" {table_name:<25} {e.__class__.__name__}: {e}")
165+
166+
print("\nORM povezivanje završeno.")
167+
168+
if __name__ == "__main__":
169+
main()
170+
```
171+
172+
### Pokretanje
173+
174+
- Generiši ORM modele:
175+
176+
```sh
177+
python3 admin.sqlite_exporter.py
178+
```
179+
180+
- Testiraj ih:
181+
182+
```sh
183+
python3 jam_orm_loader.py
184+
```
185+
186+
- Ako sve radi, očekivani izlaz:
187+
188+
```sh
189+
Pronađene tabele u bazi:
190+
• SYS_COUNTRIES
191+
• SYS_FIELDS
192+
• SYS_ITEMS
193+
• SYS_PARAMS
194+
• SYS_PRIVILEGES
195+
Brz pregled SYS_ tabela:
196+
SYS_COUNTRIES → 250 redova
197+
SYS_FIELDS → 354 redova
198+
SYS_ITEMS → 73 redova
199+
SYS_PARAMS → 1 red
200+
SYS_PRIVILEGES → 0 redova
201+
ORM povezivanje završeno.
202+
```

0 commit comments

Comments
 (0)