feat: orm support for db calls
sample call from debugger_halt():
`getDb().simple_select_all("mecze", id_meczu=1)`
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from functools import wraps
|
||||||
from sqlalchemy import ForeignKey, select, insert, update
|
from sqlalchemy import ForeignKey, select, insert, update
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session, relationship
|
||||||
from typing import List
|
from typing import List
|
||||||
@@ -12,9 +13,14 @@ class baza():
|
|||||||
# global sportowcy, trofea, sportowcy_w_meczach, statystyki_sportowcow, kluby, mecze
|
# global sportowcy, trofea, sportowcy_w_meczach, statystyki_sportowcow, kluby, mecze
|
||||||
|
|
||||||
db = None
|
db = None
|
||||||
|
entities = {}
|
||||||
|
session = None
|
||||||
|
app = None
|
||||||
|
|
||||||
def __init__(self, app, config):
|
def __init__(self, app, config):
|
||||||
self.db = self.initDB(app, config)
|
self.app = app
|
||||||
|
self.db = self.initDB(self.app, config)
|
||||||
|
self.refresh_session()
|
||||||
|
|
||||||
def initDB(self, app, config):
|
def initDB(self, app, config):
|
||||||
global sportowcy, trofea, sportowcy_w_meczach, statystyki_sportowcow, kluby, mecze
|
global sportowcy, trofea, sportowcy_w_meczach, statystyki_sportowcow, kluby, mecze
|
||||||
@@ -48,6 +54,9 @@ class baza():
|
|||||||
statystyki: Mapped[List["statystyki_sportowcow"]] = relationship(back_populates="sportowiec")
|
statystyki: Mapped[List["statystyki_sportowcow"]] = relationship(back_populates="sportowiec")
|
||||||
trofea: Mapped[ List["trofea"]] = relationship(back_populates="zawodnik", foreign_keys="[trofea.id_zawodnika]")
|
trofea: Mapped[ List["trofea"]] = relationship(back_populates="zawodnik", foreign_keys="[trofea.id_zawodnika]")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Sportowiec #{self.id_zawodnika} ({self.imie} {self.nazwisko})>"
|
||||||
|
|
||||||
# Co było pierwsze, jajko czy kura? https://docs.sqlalchemy.org/en/20/orm/relationship_persistence.html#rows-that-point-to-themselves-mutually-dependent-rows
|
# Co było pierwsze, jajko czy kura? https://docs.sqlalchemy.org/en/20/orm/relationship_persistence.html#rows-that-point-to-themselves-mutually-dependent-rows
|
||||||
# Kiepskie rozwiązanie, ale jednak działające: pozwolić obcym kluczom na bycie "null"
|
# Kiepskie rozwiązanie, ale jednak działające: pozwolić obcym kluczom na bycie "null"
|
||||||
class trofea(Base):
|
class trofea(Base):
|
||||||
@@ -59,6 +68,9 @@ class baza():
|
|||||||
sezon: Mapped[ str] = mapped_column()
|
sezon: Mapped[ str] = mapped_column()
|
||||||
rok: Mapped[ int] = mapped_column()
|
rok: Mapped[ int] = mapped_column()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Trofeum #{self.id_trofeum} ({self.nazwa})>"
|
||||||
|
|
||||||
class sportowcy_w_meczach(Base):
|
class sportowcy_w_meczach(Base):
|
||||||
__tablename__ = tnp + "sportowcy_w_meczach"
|
__tablename__ = tnp + "sportowcy_w_meczach"
|
||||||
id_rekordu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
id_rekordu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
@@ -75,6 +87,9 @@ class baza():
|
|||||||
wygrana: Mapped[ int] = mapped_column()
|
wygrana: Mapped[ int] = mapped_column()
|
||||||
wynik: Mapped[ float] = mapped_column()
|
wynik: Mapped[ float] = mapped_column()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Sportowiec #{self.id_zawodnika} ({self.imie} {self.nazwisko})>"
|
||||||
|
|
||||||
class statystyki_sportowcow(Base):
|
class statystyki_sportowcow(Base):
|
||||||
__tablename__ = tnp + "statystyki_sportowcow"
|
__tablename__ = tnp + "statystyki_sportowcow"
|
||||||
id_statystyki: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
id_statystyki: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
@@ -93,6 +108,9 @@ class baza():
|
|||||||
wynik_sum: Mapped[ int] = mapped_column()
|
wynik_sum: Mapped[ int] = mapped_column()
|
||||||
meczow_do_wynikow_sum: Mapped[ int] = mapped_column()
|
meczow_do_wynikow_sum: Mapped[ int] = mapped_column()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Statystyka #{self.id_statystyki} ({self.sportowiec.imie} {self.sportowiec.nazwisko})>"
|
||||||
|
|
||||||
class kluby(Base):
|
class kluby(Base):
|
||||||
__tablename__ = tnp + "kluby"
|
__tablename__ = tnp + "kluby"
|
||||||
id_klubu: Mapped[ str] = mapped_column(primary_key=True)
|
id_klubu: Mapped[ str] = mapped_column(primary_key=True)
|
||||||
@@ -101,6 +119,9 @@ class baza():
|
|||||||
sportowcy_w_klubie: Mapped[ List["sportowcy"]] = relationship(back_populates="klub", foreign_keys="[sportowcy.klub_id]")
|
sportowcy_w_klubie: Mapped[ List["sportowcy"]] = relationship(back_populates="klub", foreign_keys="[sportowcy.klub_id]")
|
||||||
sportowcy_ostatni_gol: Mapped[ "sportowcy"] = relationship(back_populates="ostatni_gol_dla", foreign_keys="[sportowcy.ostatni_gol_dla_id]")
|
sportowcy_ostatni_gol: Mapped[ "sportowcy"] = relationship(back_populates="ostatni_gol_dla", foreign_keys="[sportowcy.ostatni_gol_dla_id]")
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Klub #{self.id_klubu} ({self.skrocona_nazwa})>"
|
||||||
|
|
||||||
class mecze(Base):
|
class mecze(Base):
|
||||||
__tablename__ = tnp + "mecze"
|
__tablename__ = tnp + "mecze"
|
||||||
id_meczu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
id_meczu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
|
||||||
@@ -117,25 +138,64 @@ class baza():
|
|||||||
skrocona_nazwa_turnieju: Mapped[ str] = mapped_column()
|
skrocona_nazwa_turnieju: Mapped[ str] = mapped_column()
|
||||||
flaga: Mapped[ int] = mapped_column()
|
flaga: Mapped[ int] = mapped_column()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"<Mecz #{self.id_meczu} ({self.zewnetrzne_id_meczu}, {self.gospodarze.skrocona_nazwa} vs. {self.goscie.skrocona_nazwa})>"
|
||||||
|
|
||||||
|
self.entities = {
|
||||||
|
'sportowcy': sportowcy,
|
||||||
|
'trofea': trofea,
|
||||||
|
'sportowcy_w_meczach': sportowcy_w_meczach,
|
||||||
|
'statystyki_sportowcow': statystyki_sportowcow,
|
||||||
|
'kluby': kluby,
|
||||||
|
'mecze': mecze
|
||||||
|
}
|
||||||
|
|
||||||
return db
|
return db
|
||||||
|
|
||||||
def create_all(self):
|
def create_all(self):
|
||||||
self.db.create_all()
|
self.db.create_all()
|
||||||
|
|
||||||
def simple_select_all(self, type, **kwargs):
|
def refresh_session(self):
|
||||||
|
with self.app.app_context():
|
||||||
|
self.session = Session(self.db.engine)
|
||||||
|
|
||||||
|
def exit_gracefully(func):
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
return_val = None
|
||||||
|
try:
|
||||||
|
return_val = func(self, *args, **kwargs)
|
||||||
|
except:
|
||||||
|
self.session.rollback()
|
||||||
|
self.session.close()
|
||||||
|
self.refresh_session()
|
||||||
|
return return_val
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
@exit_gracefully
|
||||||
|
def simple_select_all(self, entity_type, **kwargs):
|
||||||
"""
|
"""
|
||||||
Użycie:
|
Użycie:
|
||||||
simple_select_all(ldb.sportowcy, zewnetrzne_id_zawodnika="").fetchall()
|
simple_select_all(ldb.sportowcy, zewnetrzne_id_zawodnika="MVC8zHZD")
|
||||||
|
simple_select_all("sportowcy", id_zawodnika=1)
|
||||||
|
|
||||||
https://stackoverflow.com/a/75316945
|
https://stackoverflow.com/a/75316945
|
||||||
Did they make it harder to query dynamically on purpose? ~Frank 19.11.2023
|
Did they make it harder to query dynamically on purpose? ~Frank 19.11.2023
|
||||||
"""
|
"""
|
||||||
with self.db.engine.begin() as conn:
|
|
||||||
return conn.execute(
|
|
||||||
select(type).
|
|
||||||
filter_by(**kwargs)
|
|
||||||
).scalars()
|
|
||||||
|
|
||||||
|
if not isinstance(entity_type, str):
|
||||||
|
entity_type = entity_type.__name__
|
||||||
|
|
||||||
|
results = (
|
||||||
|
self.session.
|
||||||
|
query(self.entities[entity_type]).
|
||||||
|
filter_by(**kwargs).
|
||||||
|
all()
|
||||||
|
)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
@exit_gracefully
|
||||||
def simple_insert_one(self, type, **kwargs):
|
def simple_insert_one(self, type, **kwargs):
|
||||||
"""
|
"""
|
||||||
Użycie:
|
Użycie:
|
||||||
@@ -151,6 +211,7 @@ class baza():
|
|||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@exit_gracefully
|
||||||
def simple_insert_many(self, objs_list):
|
def simple_insert_many(self, objs_list):
|
||||||
"""
|
"""
|
||||||
Użycie:
|
Użycie:
|
||||||
@@ -165,6 +226,7 @@ class baza():
|
|||||||
return 0
|
return 0
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@exit_gracefully
|
||||||
def sample_data_init(self, override_safety_check=False):
|
def sample_data_init(self, override_safety_check=False):
|
||||||
"""
|
"""
|
||||||
Użycie:
|
Użycie:
|
||||||
@@ -176,8 +238,13 @@ class baza():
|
|||||||
sample_data_init(override_safety_check=True)
|
sample_data_init(override_safety_check=True)
|
||||||
Metoda głównie używana do testów.
|
Metoda głównie używana do testów.
|
||||||
"""
|
"""
|
||||||
is_table_empty = self.simple_select_all(sportowcy, zewnetrzne_id_zawodnika="MVC8zHZD").one() is None
|
is_table_empty = False
|
||||||
if not is_table_empty and not override_safety_check:
|
try:
|
||||||
|
self.simple_select_all(self.sportowcy, zewnetrzne_id_zawodnika="MVC8zHZD")
|
||||||
|
except:
|
||||||
|
is_table_empty = True
|
||||||
|
|
||||||
|
if not is_table_empty and override_safety_check:
|
||||||
raise EnvironmentError("sample_data_init() ran on a non-empty database. Ignore with override_safety_check=True.")
|
raise EnvironmentError("sample_data_init() ran on a non-empty database. Ignore with override_safety_check=True.")
|
||||||
|
|
||||||
with Session(self.db.engine) as session:
|
with Session(self.db.engine) as session:
|
||||||
|
|||||||
Reference in New Issue
Block a user