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" %}
-
-
-
-
- | Genre |
- Aktionen |
-
-
-
- {% for genre in genres %}
-
- | {{ genre["Genre"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
-
-
-
-
- | Name |
- Aktionen |
-
-
-
- {% for hrsg in herausgeber %}
-
- | {{ hrsg["Name"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
-
-
-
-
- | Pseudonym |
- Aktionen |
-
-
-
- {% for pseudonym in pseudonyme %}
-
- | {{ pseudonym["Pseudonym"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
+
+
+
+
+ | {{ model | capitalize }} |
+ Aktionen |
+
+
+
+ {% for item in items %}
+
+ | {{ item[column] }} |
+
+
+
+
+ |
+
+
+ |
+
+ {% endfor %}
+
+
+
+
+{% 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" %}
-
-
-
-
- | Sprachen |
- Aktionen |
-
-
-
- {% for sprache in sprachen %}
-
- | {{ sprache["Sprache"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
-
-
-
-
- | Textformen |
- Aktionen |
-
-
-
- {% for textform in textformen %}
-
- | {{ textform["Textform"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
-
-
-
-
- | Verlag |
- Aktionen |
-
-
-
- {% for verlag in verlage %}
-
- | {{ verlag["Verlag"] }} |
- |
- |
-
- {% endfor %}
-
-
-
-
-{% 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" %}
-
-
-
-
-{% 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"))
-