From f4b0ec6045ce55a8bf8ba5b8d85da665c7a98f54 Mon Sep 17 00:00:00 2001 From: eclipse Date: Mon, 28 Jul 2025 22:46:33 +0200 Subject: [PATCH] switched handling of all simple tables (ID and one other column) to generic class-based view and template --- the_works/__init__.py | 33 +++--- the_works/models.py | 84 ++++++++------ the_works/old_models.py | 121 -------------------- the_works/tables.py | 125 --------------------- the_works/templates/views/genre.html | 70 ------------ the_works/templates/views/herausgeber.html | 70 ------------ the_works/templates/views/pseudonym.html | 70 ------------ the_works/templates/views/simple_view.html | 84 ++++++++++++++ the_works/templates/views/sprache.html | 70 ------------ the_works/templates/views/textform.html | 70 ------------ the_works/templates/views/verlag.html | 70 ------------ the_works/templates/views/werksform.html | 70 ------------ the_works/views/genre.py | 38 ------- the_works/views/herausgeber.py | 35 ------ the_works/views/pseudonym.py | 35 ------ the_works/views/sprache.py | 35 ------ the_works/views/textform.py | 35 ------ the_works/views/verlag.py | 35 ------ the_works/views/view.py | 65 +++++++++++ the_works/views/werksform.py | 35 ------ 20 files changed, 217 insertions(+), 1033 deletions(-) delete mode 100644 the_works/old_models.py delete mode 100644 the_works/tables.py delete mode 100644 the_works/templates/views/genre.html delete mode 100644 the_works/templates/views/herausgeber.html delete mode 100644 the_works/templates/views/pseudonym.html create mode 100644 the_works/templates/views/simple_view.html delete mode 100644 the_works/templates/views/sprache.html delete mode 100644 the_works/templates/views/textform.html delete mode 100644 the_works/templates/views/verlag.html delete mode 100644 the_works/templates/views/werksform.html delete mode 100644 the_works/views/genre.py delete mode 100644 the_works/views/herausgeber.py delete mode 100644 the_works/views/pseudonym.py delete mode 100644 the_works/views/sprache.py delete mode 100644 the_works/views/textform.py delete mode 100644 the_works/views/verlag.py create mode 100644 the_works/views/view.py delete mode 100644 the_works/views/werksform.py diff --git a/the_works/__init__.py b/the_works/__init__.py index 9347c99..356652e 100644 --- a/the_works/__init__.py +++ b/the_works/__init__.py @@ -1,12 +1,10 @@ from flask import Flask - -# this import is not strictly necessary but it forces pipreqs-to include dotenv when generating `requirements.txt` -import dotenv - +import dotenv # this import is not strictly necessary but it forces pipreqs-to include dotenv when generating `requirements.txt` from the_works.database import init_db -from the_works.views import home, text, werk, verlag, sprache, textform, werksform, genre, pseudonym, reihe, herausgeber, veroeffentlichung, titelbild +from the_works.models import CLASSVIEWABLE_MODELS +from the_works.views import home, text, werk, reihe, veroeffentlichung, titelbild +from the_works.views.view import VIEWS, ViewAll, ViewCreate, ViewUpdate, ViewDelete -#from flask_debugtoolbar import DebugToolbarExtension def create_app(config=None): app = Flask(__name__) @@ -24,23 +22,28 @@ def create_app(config=None): # some #DEBUG output print(f"Current Environment: {app.config['ENV'] if 'ENV' in app.config.keys() else 'ENV is not set'}") #DEBUG - print(app.config) #DEBUG # initialize database init_db(app) - # register blueprints - app.register_blueprint(genre.bp) - app.register_blueprint(herausgeber.bp) + # add url rules for class-based views + for m in CLASSVIEWABLE_MODELS: + for v in VIEWS: + route = f"/{m["name"]}/{v['name']}{v.get('route_params', '')}" + class_ = globals()[f"View{v['name'].capitalize()}"] + view_name = f"{m["name"]}.{v['name']}" + kwargs = {key: value for key, value in m.items() if key is not "name"} + app.add_url_rule( + route, + endpoint=view_name, + view_func=class_.as_view(view_name, m["name"], **kwargs) + ) + + # register blueprints for remaining views app.register_blueprint(home.bp) - app.register_blueprint(pseudonym.bp) app.register_blueprint(reihe.bp) - app.register_blueprint(sprache.bp) app.register_blueprint(text.bp) - app.register_blueprint(textform.bp) - app.register_blueprint(verlag.bp) app.register_blueprint(werk.bp) - app.register_blueprint(werksform.bp) app.register_blueprint(veroeffentlichung.bp) app.register_blueprint(titelbild.bp) diff --git a/the_works/models.py b/the_works/models.py index 5832b76..4eb2740 100644 --- a/the_works/models.py +++ b/the_works/models.py @@ -1,11 +1,22 @@ import sys from typing import List, Optional from sqlalchemy import ForeignKey, types, CheckConstraint -from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship, validates +from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy from flask import url_for +CLASSVIEWABLE_MODELS = [ + {"name": "genre", "title": "Genres"}, + {"name": "herausgeber", "title": "Herausgeber", "column": "Name"}, + {"name": "pseudonym", "title": "Pseudonyme"}, + {"name": "sprache", "title": "Sprachen"}, + {"name": "textform", "title": "Textformen"}, + {"name": "verlag", "title": "Verlage"}, + {"name": "werksform", "title": "Werksformen"} +] + +"""Base class for the_works' data models""" class Base(DeclarativeBase): def asdict(self) -> dict: d = {} @@ -23,6 +34,8 @@ class Base(DeclarativeBase): return f"{type(self).__name__}({str(self.asdict())})" +# Classes for models with a single column (plus ID) which can be handled by the generic class-based view + class Genre(Base): __tablename__ = 'Genre' @@ -69,6 +82,40 @@ class Textform(Base): text: Mapped[List['Text']] = relationship(back_populates='textform') +class Verlag(Base): + __tablename__ = 'Verlag' + + ID: Mapped[int] = mapped_column(primary_key=True) + Verlag: Mapped[str] = mapped_column(CheckConstraint('Verlag <> ""', name='VerlagNotEmptyConstraint'), unique=True) + + reihe: Mapped[List['Reihe']] = relationship(back_populates='verlag') + werk: Mapped[List['Werk']] = relationship(back_populates='verlag') + + +class Werksform(Base): + __tablename__ = 'Werksform' + + ID: Mapped[int] = mapped_column(primary_key=True) + Werksform: Mapped[str] = mapped_column(CheckConstraint('Werksform <> ""', name='WerksformNotEmptyConstraint'), unique=True) + + werk: Mapped[List['Werk']] = relationship(back_populates='werksform') + + +# Classes that have more than one column and need dedicated view functions + +class Reihe(Base): + __tablename__ = 'Reihe' + + ID: Mapped[int] = mapped_column(primary_key=True) + Titel: Mapped[str] = mapped_column(CheckConstraint('Titel <> ""', name='ReihentitelNotEmptyConstraint')) + + Verlag: Mapped[Optional[str]] = mapped_column(ForeignKey('Verlag.ID')) + verlag: Mapped['Verlag'] = relationship(back_populates='reihe') + + text: Mapped[List['Text']] = relationship(back_populates='reihe') + werk: Mapped[List['Werk']] = relationship(back_populates='reihe') + + class Titelbild(Base): __tablename__ = 'Titelbild' @@ -91,38 +138,6 @@ class Titelbild(Base): return tb -class Verlag(Base): - __tablename__ = 'Verlag' - - ID: Mapped[int] = mapped_column(primary_key=True) - Verlag: Mapped[str] = mapped_column(CheckConstraint('Verlag <> ""', name='VerlagNotEmptyConstraint'), unique=True) - - reihe: Mapped[List['Reihe']] = relationship(back_populates='verlag') - werk: Mapped[List['Werk']] = relationship(back_populates='verlag') - - -class Werksform(Base): - __tablename__ = 'Werksform' - - ID: Mapped[int] = mapped_column(primary_key=True) - Werksform: Mapped[str] = mapped_column(CheckConstraint('Werksform <> ""', name='WerksformNotEmptyConstraint'), unique=True) - - werk: Mapped[List['Werk']] = relationship(back_populates='werksform') - - -class Reihe(Base): - __tablename__ = 'Reihe' - - ID: Mapped[int] = mapped_column(primary_key=True) - Titel: Mapped[str] = mapped_column(CheckConstraint('Titel <> ""', name='ReihentitelNotEmptyConstraint')) - - Verlag: Mapped[Optional[str]] = mapped_column(ForeignKey('Verlag.ID')) - verlag: Mapped['Verlag'] = relationship(back_populates='reihe') - - text: Mapped[List['Text']] = relationship(back_populates='reihe') - werk: Mapped[List['Werk']] = relationship(back_populates='reihe') - - class Text(Base): __tablename__ = 'Text' @@ -147,7 +162,6 @@ class Text(Base): genre_ids: AssociationProxy[List["Genre"]] = association_proxy("genres", "Genre", creator=lambda genre_id: Text_Genre(Genre=genre_id)) - class Werk(Base): __tablename__ = 'Werk' @@ -201,6 +215,8 @@ class Veroeffentlichung(Base): werk: Mapped['Werk'] = relationship(back_populates='veroeffentlichung') +# Additional tables for many-to-many-relationships within the DB + class Text_Genre(Base): __tablename__ = 'Text_Genre' diff --git a/the_works/old_models.py b/the_works/old_models.py deleted file mode 100644 index a188895..0000000 --- a/the_works/old_models.py +++ /dev/null @@ -1,121 +0,0 @@ -from the_works.database import db -from sqlalchemy.orm import relationship -from sqlalchemy.ext.associationproxy import association_proxy -from flask import url_for -import sys - -# add method to sqlalchemy.orm.decl_api.Model -def _asdict(self): - d = {} - for col in self.__table__.c: - if type(col.type) == db.types.BLOB: - d[col.key] = "Blob (NULL)" if self.__getattribute__(col.key) == None else f"Blob ({sys.getsizeof(self.__getattribute__(col.key))} Bytes)" - else: - value = str(self.__getattribute__(col.key)) - d[col.key] = value[:50] + '...' if len(value) > 50 else value - return d -db.Model._asdict = _asdict - -# override repr() method from sqlalchemy.orm.decl_api.Model -def __repr__(self): - return f"{type(self).__name__}({str(self._asdict())})" -db.Model.__repr__ = __repr__ - -class Text(db.Model): - __table__ = db.Model.metadata.tables['Text'] - reihe = relationship("Reihe", back_populates="text") - textform = relationship("Textform", back_populates="text") - sprache = relationship("Sprache", back_populates="text") - veroeffentlichung = relationship("Veroeffentlichung", back_populates="text") - text_genre = relationship("Text_Genre", back_populates="text", cascade="save-update, merge, delete, delete-orphan") - genres = association_proxy("text_genre", "Genre") - -class Werk(db.Model): - __table__ = db.Model.metadata.tables['Werk'] - reihe = relationship("Reihe", back_populates="werk") - verlag = relationship("Verlag", back_populates="werk") - werksform = relationship("Werksform", back_populates="werk") - veroeffentlichung = relationship("Veroeffentlichung", back_populates="werk") - werk_genre = relationship("Werk_Genre", back_populates="werk", cascade="save-update, merge, delete, delete-orphan") -# titelbild = relationship("Titelbild", back_populates="werk", cascade="all, delete-orphan", single_parent=True) - titelbild = relationship("Titelbild", back_populates="werk") - genres = association_proxy("werk_genre", "Genre") - werk_herausgeber = relationship("Werk_Herausgeber", back_populates="werk", cascade="save-update, merge, delete, delete-orphan") - herausgeber = association_proxy("werk_herausgeber", "Herausgeber") - -class Veroeffentlichung(db.Model): - __table__ = db.Model.metadata.tables['Veroeffentlichung'] - text = relationship("Text", back_populates="veroeffentlichung") - werk = relationship("Werk", back_populates="veroeffentlichung") - pseudonym = relationship("Pseudonym", back_populates="veroeffentlichung") - -class Reihe(db.Model): - __table__ = db.Model.metadata.tables['Reihe'] - text = relationship("Text", back_populates="reihe") - werk = relationship("Werk", back_populates="reihe") - verlag = relationship("Verlag", back_populates="reihe") - -class Verlag(db.Model): - __table__ = db.Model.metadata.tables['Verlag'] - werk = relationship("Werk", back_populates="verlag") - reihe = relationship("Reihe", back_populates="verlag") - -class Sprache(db.Model): - __table__ = db.Model.metadata.tables['Sprache'] - text = relationship("Text", back_populates="sprache") - -class Textform(db.Model): - __table__ = db.Model.metadata.tables['Textform'] - text = relationship("Text", back_populates="textform") - -class Werksform(db.Model): - __table__ = db.Model.metadata.tables['Werksform'] - werk = relationship("Werk", back_populates="werksform") - -class Genre(db.Model): - __table__ = db.Model.metadata.tables['Genre'] - text_genre = relationship("Text_Genre", back_populates="genre") - werk_genre = relationship("Werk_Genre", back_populates="genre") - -class Pseudonym(db.Model): - __table__ = db.Model.metadata.tables['Pseudonym'] - veroeffentlichung = relationship("Veroeffentlichung", back_populates="pseudonym") - -class Herausgeber(db.Model): - __table__ = db.Model.metadata.tables['Herausgeber'] - werk_herausgeber = relationship("Werk_Herausgeber", back_populates="herausgeber") - -class Titelbild(db.Model): - __table__ = db.Model.metadata.tables['Titelbild'] - werk = relationship("Werk", back_populates="titelbild") - - def _asdict_with_urls(self): - tb = self._asdict() - tb["Bild"] = url_for("titelbild.image", id=self.ID) - tb["Thumbnail"] = url_for("titelbild.thumbnail", id=self.ID) - return tb - -class Text_Genre(db.Model): - __table__ = db.Model.metadata.tables['Text_Genre'] - text = relationship("Text", back_populates="text_genre") - genre = relationship("Genre", back_populates="text_genre") - - def __init__(self, genre: int): - self.Genre = genre - -class Werk_Genre(db.Model): - __table__ = db.Model.metadata.tables['Werk_Genre'] - werk = relationship("Werk", back_populates="werk_genre") - genre = relationship("Genre", back_populates="werk_genre") - - def __init__(self, genre: int): - self.Genre = genre - -class Werk_Herausgeber(db.Model): - __table__ = db.Model.metadata.tables['Werk_Herausgeber'] - werk = relationship("Werk", back_populates="werk_herausgeber") - herausgeber = relationship("Herausgeber", back_populates="werk_herausgeber") - - def __init__(self, hrsg: int): - self.Herausgeber = hrsg - diff --git a/the_works/tables.py b/the_works/tables.py deleted file mode 100644 index eddc474..0000000 --- a/the_works/tables.py +++ /dev/null @@ -1,125 +0,0 @@ -# this is the verbatim output of `sqlacodegen --generator tables sqlite:///path/to/the_works.sqlite`, run inside project root - -from sqlalchemy import Column, ForeignKey, Integer, LargeBinary, MetaData, Table, Text - -metadata = MetaData() - - -t_Genre = Table( - 'Genre', metadata, - Column('ID', Integer, primary_key=True), - Column('Genre', Text, nullable=False) -) - -t_Herausgeber = Table( - 'Herausgeber', metadata, - Column('ID', Integer, primary_key=True), - Column('Name', Text, nullable=False) -) - -t_Pseudonym = Table( - 'Pseudonym', metadata, - Column('ID', Integer, primary_key=True), - Column('Pseudonym', Text, nullable=False) -) - -t_Sprache = Table( - 'Sprache', metadata, - Column('ID', Integer, primary_key=True), - Column('Sprache', Text, nullable=False) -) - -t_Textform = Table( - 'Textform', metadata, - Column('ID', Integer, primary_key=True), - Column('Textform', Text, nullable=False) -) - -t_Titelbild = Table( - 'Titelbild', metadata, - Column('ID', Integer, primary_key=True), - Column('Mimetype', Text, nullable=False), - Column('Dateiname', Text, nullable=False), - Column('Dateigroesse', Integer, nullable=False), - Column('Breite', Integer, nullable=False), - Column('Hoehe', Integer, nullable=False), - Column('Bild', LargeBinary, nullable=False), - Column('Thumbnail', LargeBinary, nullable=False), - Column('sha256', Text, nullable=False, unique=True) -) - -t_Verlag = Table( - 'Verlag', metadata, - Column('ID', Integer, primary_key=True), - Column('Verlag', Text, nullable=False) -) - -t_Werksform = Table( - 'Werksform', metadata, - Column('ID', Integer, primary_key=True), - Column('Werksform', Text, nullable=False) -) - -t_Reihe = Table( - 'Reihe', metadata, - Column('ID', Integer, primary_key=True), - Column('Titel', Text, nullable=False), - Column('Verlag', ForeignKey('Verlag.ID')) -) - -t_Text = Table( - 'Text', metadata, - Column('ID', Integer, primary_key=True), - Column('Titel', Text, nullable=False), - Column('Untertitel', Text), - Column('Reihe', ForeignKey('Reihe.ID')), - Column('Textform', ForeignKey('Textform.ID')), - Column('Sprache', ForeignKey('Sprache.ID')) -) - -t_Werk = Table( - 'Werk', metadata, - Column('ID', Integer, primary_key=True), - Column('Titel', Text, nullable=False), - Column('Untertitel', Text), - Column('Werksform', ForeignKey('Werksform.ID')), - Column('Verlag', ForeignKey('Verlag.ID')), - Column('Reihe', ForeignKey('Reihe.ID')), - Column('Reihennummer', Text), - Column('Erscheinungsdatum', Text), - Column('ISBN_13', Text), - Column('ISBN_10', Text), - Column('ISSN', Text), - Column('Preis', Text), - Column('Titelbild', ForeignKey('Titelbild.ID')), - Column('Klappentext', Text), - Column('Anmerkungen', Text) -) - -t_Text_Genre = Table( - 'Text_Genre', metadata, - Column('Text', ForeignKey('Text.ID'), primary_key=True), - Column('Genre', ForeignKey('Genre.ID'), primary_key=True) -) - -t_Veroeffentlichung = Table( - 'Veroeffentlichung', metadata, - Column('ID', Integer, primary_key=True), - Column('Text', ForeignKey('Text.ID'), nullable=False), - Column('Werk', ForeignKey('Werk.ID'), nullable=False), - Column('AltTitel', Text), - Column('AltUntertitel', Text), - Column('Pseudonym', ForeignKey('Pseudonym.ID'), nullable=False) -) - -t_Werk_Genre = Table( - 'Werk_Genre', metadata, - Column('Werk', ForeignKey('Werk.ID'), primary_key=True), - Column('Genre', ForeignKey('Genre.ID'), primary_key=True) -) - -t_Werk_Herausgeber = Table( - 'Werk_Herausgeber', metadata, - Column('Herausgeber', ForeignKey('Herausgeber.ID'), primary_key=True), - Column('Werk', ForeignKey('Werk.ID'), primary_key=True) -) diff --git a/the_works/templates/views/genre.html b/the_works/templates/views/genre.html deleted file mode 100644 index c6f3f88..0000000 --- a/the_works/templates/views/genre.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Genres{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Genres{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for genre in genres %} - - - - - - {% endfor %} - -
GenreAktionen
{{ genre["Genre"] }}
- - -
-
-
- -

-

- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/herausgeber.html b/the_works/templates/views/herausgeber.html deleted file mode 100644 index 34b0561..0000000 --- a/the_works/templates/views/herausgeber.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Herausgeber:innen{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Herausgeber:innen{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for hrsg in herausgeber %} - - - - - - {% endfor %} - -
NameAktionen
{{ hrsg["Name"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/pseudonym.html b/the_works/templates/views/pseudonym.html deleted file mode 100644 index bdbe716..0000000 --- a/the_works/templates/views/pseudonym.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Pseudonyme{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Pseudonyme{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for pseudonym in pseudonyme %} - - - - - - {% endfor %} - -
PseudonymAktionen
{{ pseudonym["Pseudonym"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/simple_view.html b/the_works/templates/views/simple_view.html new file mode 100644 index 0000000..14c9091 --- /dev/null +++ b/the_works/templates/views/simple_view.html @@ -0,0 +1,84 @@ +{% extends 'base.html' %} + +{% block title %}{{ title }}{% endblock title %} + +{% block head %} + +{% endblock head %} + +{% block heading %}{{ title }}{% endblock heading %} + +{% block content %} + +{% include "_icons.svg" %} + + + + + + + + + + {% for item in items %} + + + + + + {% endfor %} + +
{{ model | capitalize }}Aktionen
{{ item[column] }} + + + + + +
+ + +
+
+
+ +

+
+ +
+
+ +
+
+ +
+ + +
+
+
+
+{% endblock content %} + +{% block script %} + + + + +{% endblock script %} diff --git a/the_works/templates/views/sprache.html b/the_works/templates/views/sprache.html deleted file mode 100644 index 9380514..0000000 --- a/the_works/templates/views/sprache.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Sprachen{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Sprachen{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for sprache in sprachen %} - - - - - - {% endfor %} - -
SprachenAktionen
{{ sprache["Sprache"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/textform.html b/the_works/templates/views/textform.html deleted file mode 100644 index ddcd4fb..0000000 --- a/the_works/templates/views/textform.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Textformen{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Textformen{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for textform in textformen %} - - - - - - {% endfor %} - -
TextformenAktionen
{{ textform["Textform"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/verlag.html b/the_works/templates/views/verlag.html deleted file mode 100644 index 8db5f2d..0000000 --- a/the_works/templates/views/verlag.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Verlage{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Verlage{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for verlag in verlage %} - - - - - - {% endfor %} - -
VerlagAktionen
{{ verlag["Verlag"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/templates/views/werksform.html b/the_works/templates/views/werksform.html deleted file mode 100644 index 7d9150c..0000000 --- a/the_works/templates/views/werksform.html +++ /dev/null @@ -1,70 +0,0 @@ -{% extends 'base.html' %} - -{% block title %}Werksformen{% endblock title %} - -{% block head %} - -{% endblock head %} - -{% block heading %}Werksformen{% endblock heading %} - -{% block content %} - -{% include "_icons.svg" %} - - - - - - - - - - {% for werksform in werksformen %} - - - - - - {% endfor %} - -
WerksformenAktionen
{{ werksform["Werksform"] }}
- - -
-
-
- -

#

-
- -
-
- -
-
- -
- - -
-
-
-
-{% endblock content %} - -{% block script %} - - - - -{% endblock script %} diff --git a/the_works/views/genre.py b/the_works/views/genre.py deleted file mode 100644 index f9fe322..0000000 --- a/the_works/views/genre.py +++ /dev/null @@ -1,38 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Genre - -bp = Blueprint("genre", __name__) - -@bp.route("/genre") -@bp.route("/genre/all") -def all(): - return render_template("views/genre.html", genres=db.session.scalars(select(Genre))) - -@bp.route("/genre/create", methods=["POST"]) -def create(): - db.session.add(Genre(Genre=request.form.get("form_Genre", default=None))) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("genre.all"), code=303) - -@bp.route("/genre/update/", methods=["POST"]) -def update(id): - genre = db.session.get(Genre, id) - if genre: - genre.Genre = request.form.get("form_Genre", default=None) - db.session.commit() - flash("Eintrag erfolgreich geändert") - else: - flash("Fehler beim Ändern: Eintrag nicht vorhanden") - return redirect(url_for("genre.all"), code=303) - -@bp.route("/genre/delete/") -def delete(id): - genre = db.session.get(Genre, id) - db.session.delete(genre) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("genre.all")) - diff --git a/the_works/views/herausgeber.py b/the_works/views/herausgeber.py deleted file mode 100644 index c4132c0..0000000 --- a/the_works/views/herausgeber.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Herausgeber - -bp = Blueprint("herausgeber", __name__) - -@bp.route("/herausgeber") -@bp.route("/herausgeber/all") -def all(): - return render_template("views/herausgeber.html", herausgeber=db.session.scalars(select(Herausgeber))) - -@bp.route("/herausgeber/create", methods=["POST"]) -def create(): - db.session.add(Herausgeber(Name = request.form["form_Name"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("herausgeber.all"), code=303) - -@bp.route("/herausgeber/update/", methods=["POST"]) -def update(id): - herausgeber = db.session.get(Herausgeber, id) - herausgeber.Name = request.form["form_Name"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("herausgeber.all"), code=303) - -@bp.route("/herausgeber/delete/") -def delete(id): - herausgeber = db.session.get(Herausgeber, id) - db.session.delete(herausgeber) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("herausgeber.all")) - diff --git a/the_works/views/pseudonym.py b/the_works/views/pseudonym.py deleted file mode 100644 index 48e724b..0000000 --- a/the_works/views/pseudonym.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Pseudonym - -bp = Blueprint("pseudonym", __name__) - -@bp.route("/pseudonym") -@bp.route("/pseudonym/all") -def all(): - return render_template("views/pseudonym.html", pseudonyme=db.session.scalars(select(Pseudonym))) - -@bp.route("/pseudonym/create", methods=["POST"]) -def create(): - db.session.add(Pseudonym(Pseudonym = request.form["form_Pseudonym"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("pseudonym.all"), code=303) - -@bp.route("/pseudonym/update/", methods=["POST"]) -def update(id): - pseudonym = db.session.get(Pseudonym, id) - pseudonym.Pseudonym = request.form["form_Pseudonym"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("pseudonym.all"), code=303) - -@bp.route("/pseudonym/delete/") -def delete(id): - pseudonym = db.session.get(Pseudonym, id) - db.session.delete(pseudonym) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("pseudonym.all")) - diff --git a/the_works/views/sprache.py b/the_works/views/sprache.py deleted file mode 100644 index 2190460..0000000 --- a/the_works/views/sprache.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Sprache - -bp = Blueprint("sprache", __name__) - -@bp.route("/sprache") -@bp.route("/sprache/all") -def all(): - return render_template("views/sprache.html", sprachen=db.session.scalars(select(Sprache))) - -@bp.route("/sprache/create", methods=["POST"]) -def create(): - db.session.add(Sprache(Sprache = request.form["form_Sprache"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("sprache.all"), code=303) - -@bp.route("/sprache/update/", methods=["POST"]) -def update(id): - sprache = db.session.get(Sprache, id) - sprache.Sprache = request.form["form_Sprache"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("sprache.all"), code=303) - -@bp.route("/sprache/delete/") -def delete(id): - sprache = db.session.get(Sprache, id) - db.session.delete(sprache) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("sprache.all")) - diff --git a/the_works/views/textform.py b/the_works/views/textform.py deleted file mode 100644 index 1f9e05e..0000000 --- a/the_works/views/textform.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Textform - -bp = Blueprint("textform", __name__) - -@bp.route("/textform") -@bp.route("/textform/all") -def all(): - return render_template("views/textform.html", textformen=db.session.scalars(select(Textform))) - -@bp.route("/textform/create", methods=["POST"]) -def create(): - db.session.add(Textform(Textform = request.form["form_Textform"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("textform.all"), code=303) - -@bp.route("/textform/update/", methods=["POST"]) -def update(id): - textform = db.session.get(Textform, id) - textform.Textform = request.form["form_Textform"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("textform.all"), code=303) - -@bp.route("/textform/delete/") -def delete(id): - textform = db.session.get(Textform, id) - db.session.delete(textform) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("textform.all")) - diff --git a/the_works/views/verlag.py b/the_works/views/verlag.py deleted file mode 100644 index f7389fa..0000000 --- a/the_works/views/verlag.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Verlag - -bp = Blueprint("verlag", __name__) - -@bp.route("/verlag") -@bp.route("/verlag/all") -def all(): - return render_template("views/verlag.html", verlage=db.session.scalars(select(Verlag))) - -@bp.route("/verlag/create", methods=["POST"]) -def create(): - db.session.add(Verlag(Verlag = request.form["form_Verlag"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("verlag.all"), code=303) - -@bp.route("/verlag/update/", methods=["POST"]) -def update(id): - verlag = db.session.get(Verlag, id) - verlag.Verlag = request.form["form_Verlag"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("verlag.all"), code=303) - -@bp.route("/verlag/delete/") -def delete(id): - verlag = db.session.get(Verlag, id) - db.session.delete(verlag) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("verlag.all")) - diff --git a/the_works/views/view.py b/the_works/views/view.py new file mode 100644 index 0000000..dcd17b1 --- /dev/null +++ b/the_works/views/view.py @@ -0,0 +1,65 @@ +from abc import ABC +from flask import render_template, request, redirect, flash, url_for +from flask.views import View +from sqlalchemy import select +from the_works.database import db + +VIEWS = [ + {"name": "all"}, + {"name": "create"}, + {"name": "update", "route_params": "/"}, + {"name": "delete", "route_params": "/"} +] + + +class ViewBase(View, ABC): + + init_every_request = False + + def __init__(self, model, **kwargs): + self.model = model.lower() + self.Model = self.model.capitalize() + module_ = __import__("the_works.models", fromlist=[self.Model]) + self.class_ = getattr(module_, self.Model) + self.title = kwargs["title"] + self.column = kwargs.get("column", self.Model) + + +class ViewAll(ViewBase): + methods = ["GET"] + def dispatch_request(self): + return render_template(f"views/classviewable.html", items=db.session.scalars(select(self.class_)), title=self.title, model=self.model, column=self.column) + + +class ViewCreate(ViewBase): + methods = ["POST"] + def dispatch_request(self): + kwargs = {self.column: request.form.get(f"form_{self.column}", default=None)} + db.session.add(self.class_(**kwargs)) + db.session.commit() + flash("Eintrag erfolgreich hinzugefügt") + return redirect(url_for(f"{self.model}.all"), code=303) + + +class ViewUpdate(ViewBase): + methods = ["POST"] + def dispatch_request(self, id: int): + record = db.session.get(self.class_, id) + if record: + setattr(record, self.column, request.form.get(f"form_{self.column}", default=None)) + db.session.commit() + flash("Eintrag erfolgreich geändert") + else: + flash("Fehler beim Ändern: Eintrag nicht vorhanden") + return redirect(url_for(f"{self.model}.all"), code=303) + + +class ViewDelete(ViewBase): + methods = ["GET"] + def dispatch_request(self, id: int): + record = db.session.get(self.class_, id) + db.session.delete(record) + db.session.commit() + flash("Eintrag erfolgreich gelöscht") + return redirect(url_for(f"{self.model}.all")) + diff --git a/the_works/views/werksform.py b/the_works/views/werksform.py deleted file mode 100644 index 41af10f..0000000 --- a/the_works/views/werksform.py +++ /dev/null @@ -1,35 +0,0 @@ -from flask import Blueprint, render_template, request, redirect, flash, url_for -from sqlalchemy import select -from the_works.database import db -from the_works.models import Werksform - -bp = Blueprint("werksform", __name__) - -@bp.route("/werksform") -@bp.route("/werksform/all") -def all(): - return render_template("views/werksform.html", werksformen=db.session.scalars(select(Werksform))) - -@bp.route("/werksform/create", methods=["POST"]) -def create(): - db.session.add(Werksform(Werksform = request.form["form_Werksform"])) - db.session.commit() - flash("Eintrag erfolgreich hinzugefügt") - return redirect(url_for("werksform.all"), code=303) - -@bp.route("/werksform/update/", methods=["POST"]) -def update(id): - werksform = db.session.get(Werksform, id) - werksform.Werksform = request.form["form_Werksform"] - db.session.commit() - flash("Eintrag erfolgreich geändert") - return redirect(url_for("werksform.all"), code=303) - -@bp.route("/werksform/delete/") -def delete(id): - werksform = db.session.get(Werksform, id) - db.session.delete(werksform) - db.session.commit() - flash("Eintrag erfolgreich gelöscht") - return redirect(url_for("werksform.all")) -