switched handling of all simple tables (ID and one other column) to generic class-based view and template

This commit is contained in:
eclipse 2025-07-28 22:46:33 +02:00
parent f0a162461d
commit f4b0ec6045
20 changed files with 217 additions and 1033 deletions

View File

@ -1,12 +1,10 @@
from flask import Flask from flask import Flask
import dotenv # this import is not strictly necessary but it forces pipreqs-to include dotenv when generating `requirements.txt`
# this import is not strictly necessary but it forces pipreqs-to include dotenv when generating `requirements.txt`
import dotenv
from the_works.database import init_db 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): def create_app(config=None):
app = Flask(__name__) app = Flask(__name__)
@ -24,23 +22,28 @@ def create_app(config=None):
# some #DEBUG output # some #DEBUG output
print(f"Current Environment: {app.config['ENV'] if 'ENV' in app.config.keys() else 'ENV is not set'}") #DEBUG 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 # initialize database
init_db(app) init_db(app)
# register blueprints # add url rules for class-based views
app.register_blueprint(genre.bp) for m in CLASSVIEWABLE_MODELS:
app.register_blueprint(herausgeber.bp) 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(home.bp)
app.register_blueprint(pseudonym.bp)
app.register_blueprint(reihe.bp) app.register_blueprint(reihe.bp)
app.register_blueprint(sprache.bp)
app.register_blueprint(text.bp) app.register_blueprint(text.bp)
app.register_blueprint(textform.bp)
app.register_blueprint(verlag.bp)
app.register_blueprint(werk.bp) app.register_blueprint(werk.bp)
app.register_blueprint(werksform.bp)
app.register_blueprint(veroeffentlichung.bp) app.register_blueprint(veroeffentlichung.bp)
app.register_blueprint(titelbild.bp) app.register_blueprint(titelbild.bp)

View File

@ -1,11 +1,22 @@
import sys import sys
from typing import List, Optional from typing import List, Optional
from sqlalchemy import ForeignKey, types, CheckConstraint 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 sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy
from flask import url_for 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): class Base(DeclarativeBase):
def asdict(self) -> dict: def asdict(self) -> dict:
d = {} d = {}
@ -23,6 +34,8 @@ class Base(DeclarativeBase):
return f"{type(self).__name__}({str(self.asdict())})" 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): class Genre(Base):
__tablename__ = 'Genre' __tablename__ = 'Genre'
@ -69,6 +82,40 @@ class Textform(Base):
text: Mapped[List['Text']] = relationship(back_populates='textform') 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): class Titelbild(Base):
__tablename__ = 'Titelbild' __tablename__ = 'Titelbild'
@ -91,38 +138,6 @@ class Titelbild(Base):
return tb 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): class Text(Base):
__tablename__ = 'Text' __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)) genre_ids: AssociationProxy[List["Genre"]] = association_proxy("genres", "Genre", creator=lambda genre_id: Text_Genre(Genre=genre_id))
class Werk(Base): class Werk(Base):
__tablename__ = 'Werk' __tablename__ = 'Werk'
@ -201,6 +215,8 @@ class Veroeffentlichung(Base):
werk: Mapped['Werk'] = relationship(back_populates='veroeffentlichung') werk: Mapped['Werk'] = relationship(back_populates='veroeffentlichung')
# Additional tables for many-to-many-relationships within the DB
class Text_Genre(Base): class Text_Genre(Base):
__tablename__ = 'Text_Genre' __tablename__ = 'Text_Genre'

View File

@ -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

View File

@ -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)
)

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Genres{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Genres{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="genre-table">
<thead>
<tr>
<th>Genre</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for genre in genres %}
<tr id="genre-{{ genre['ID'] }}">
<td title="Genre">{{ genre["Genre"] }}</td>
<td class="action action-update" data-id="{{ genre['ID'] }}" data-genre="{{genre['Genre'] }}"><a href="#" title="Genre bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ genre['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('genre.delete', id=genre['ID']) }}" title="Genre löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="genre-modal">
<article>
<form id="genre_detail_form" method="post" action="{{ url_for('genre.create') }}">
<header>
<button class="modal-close" aria-label="close" formmethod="dialog" formnovalidate rel="prev"></button>
<h1 id="dialog-heading" />
</header>
<fieldset>
<article>
<label>
<span class="required">Genre</span>
<input id="form_Genre" name="form_Genre" aria-Label="Genre" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('genre.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("genre-table");
initCreateButton("genre-table", "Genre hinzufügen …");
initModal("genre-modal", "form_Genre", ["Neues Genre", "Genre bearbeiten"], ["{{ url_for('genre.create') }}", "{{ url_for('genre.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Herausgeber:innen{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Herausgeber:innen{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="herausgeber-table">
<thead>
<tr>
<th>Name</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for hrsg in herausgeber %}
<tr id="hrsg-{{ hrsg['ID'] }}">
<td title="Name">{{ hrsg["Name"] }}</td>
<td class="action action-update" data-id="{{ hrsg['ID'] }}" data-name="{{hrsg['Name'] }}"><a href="#" title="Herausgeber:in bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ hrsg['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('herausgeber.delete', id=hrsg['ID']) }}" title="Herausgeber:in löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="herausgeber-modal">
<article>
<form id="herausgeber_detail_form" method="dialog">
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Name</span>
<input id="form_Name" name="form_Name" aria-Label="Name" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('herausgeber.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("herausgeber-table");
initCreateButton("herausgeber-table", "Herausgeber:in hinzufügen …");
initModal("herausgeber-modal", "form_Name", ["Neue:r Herausgeber:in", "Herausgeber:in bearbeiten"], ["{{ url_for('herausgeber.create') }}", "{{ url_for('herausgeber.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Pseudonyme{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Pseudonyme{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="pseudonym-table">
<thead>
<tr>
<th>Pseudonym</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for pseudonym in pseudonyme %}
<tr id="pseudonym-{{ pseudonym['ID'] }}">
<td title="Pseudonym">{{ pseudonym["Pseudonym"] }}</td>
<td class="action action-update" data-id="{{ pseudonym['ID'] }}" data-pseudonym="{{pseudonym['Pseudonym'] }}"><a href="#" title="Pseudonym bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ pseudonym['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('pseudonym.delete', id=pseudonym['ID']) }}" title="Pseudonym löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="pseudonym-modal">
<article>
<form id="pseudonym_detail_form" method="dialog">
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Pseudonym</span>
<input id="form_Pseudonym" name="form_Pseudonym" aria-Label="Pseudonym" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('pseudonym.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("pseudonym-table");
initCreateButton("pseudonym-table", "Pseudonym hinzufügen …");
initModal("pseudonym-modal", "form_Pseudonym", ["Neues Pseudonym", "Pseudonym bearbeiten"], ["{{ url_for('pseudonym.create') }}", "{{ url_for('pseudonym.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -0,0 +1,84 @@
{% extends 'base.html' %}
{% block title %}{{ title }}{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}" />
{% endblock head %}
{% block heading %}{{ title }}{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="{{ model }}-table">
<thead>
<tr>
<th>{{ model | capitalize }}</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr id="{{ model }}-{{ item['ID'] }}">
<td title="{{ model | capitalize }}">{{ item[column] }}</td>
<td class="action action-update" data-id="{{ item['ID'] }}" data-{{ column }}="{{item[column] }}">
<a href="#" title="{{ model | capitalize }} bearbeiten">
<svg viewbox="0 0 24 24"><use href="#update" /></svg>
</a>
</td>
<td id="delete-{{ item['ID'] }}" class="action">
<a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for(model+'.delete', id=item['ID']) }}" title="{{ model | capitalize }} löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="{{ model }}-modal">
<article>
<form id="{{ model }}_detail_form" method="post" action="{{ url_for(model + '.create') }}">
<header>
<button class="modal-close" aria-label="close" formmethod="dialog" formnovalidate rel="prev"></button>
<h1 id="dialog-heading"></h1>
</header>
<fieldset>
<article>
<label>
<span class="required">{{ model | capitalize }}</span>
<input id="form_{{ column | capitalize }}" name="form_{{ column | capitalize }}" aria-Label="{{ column | capitalize }}" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for(model + '.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("{{ model }}-table");
initCreateButton("{{ model }}-table", "{{ model | capitalize }} hinzufügen …");
initModal(
"{{ model }}-modal",
"form_{{ column | capitalize }}",
["Neues {{ model | capitalize }}", "{{ model | capitalize }} bearbeiten"],
[
"{{ url_for(model + '.create') }}",
"{{ url_for(model + '.update', id=-1) }}",
]
);
};
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Sprachen{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Sprachen{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="sprache-table">
<thead>
<tr>
<th>Sprachen</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for sprache in sprachen %}
<tr id="sprache-{{ sprache['ID'] }}">
<td title="Sprache">{{ sprache["Sprache"] }}</td>
<td class="action action-update" data-id="{{ sprache['ID'] }}" data-sprache="{{sprache['Sprache'] }}"><a href="#" title="Sprache bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ sprache['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('sprache.delete', id=sprache['ID']) }}" title="Sprache löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="sprache-modal">
<article>
<form id="sprache_detail_form" method="dialog">
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Sprache</span>
<input id="form_Sprache" name="form_Sprache" aria-Label="Sprache" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('sprache.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("sprache-table");
initCreateButton("sprache-table", "Sprache hinzufügen …");
initModal("sprache-modal", "form_Sprache", ["Neue Sprache", "Sprache bearbeiten"], ["{{ url_for('sprache.create') }}", "{{ url_for('sprache.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Textformen{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Textformen{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="textform-table">
<thead>
<tr>
<th>Textformen</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for textform in textformen %}
<tr id="textform-{{ textform['ID'] }}">
<td title="Textform">{{ textform["Textform"] }}</td>
<td class="action action-update" data-id="{{ textform['ID'] }}" data-textform="{{textform['Textform'] }}"><a href="#" title="Textform bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ textform['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('textform.delete', id=textform['ID']) }}" title="Textform löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="textform-modal">
<article>
<form id="textform_detail_form" method="dialog">
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Textform</span>
<input id="form_Textform" name="form_Textform" aria-Label="Textform" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('textform.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("textform-table");
initCreateButton("textform-table", "Textform hinzufügen …");
initModal("textform-modal", "form_Textform", ["Neue Textform", "Textform bearbeiten"], ["{{ url_for('textform.create') }}", "{{ url_for('textform.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Verlage{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Verlage{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="verlag-table">
<thead>
<tr>
<th>Verlag</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for verlag in verlage %}
<tr id="verlag-{{ verlag['ID'] }}">
<td title="Verlag">{{ verlag["Verlag"] }}</td>
<td class="action action-update" data-id="{{ verlag['ID'] }}" data-verlag="{{verlag['Verlag'] }}"><a href="#" title="Verlag bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ verlag['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('verlag.delete', id=verlag['ID']) }}" title="Verlag löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="verlag-modal">
<article>
<form id="verlag_detail_form" method="dialog">
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Name des Verlags</span>
<input id="form_Verlag" name="form_Verlag" aria-Label="Verlagsname" required autofocus />
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="{{ url_for('verlag.create') }}">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("verlag-table");
initCreateButton("verlag-table", "Verlag hinzufügen …");
initModal("verlag-modal", "form_Verlag", ["Neuer Verlag", "Verlag bearbeiten"], ["{{ url_for('verlag.create') }}", "{{ url_for('verlag.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -1,70 +0,0 @@
{% extends 'base.html' %}
{% block title %}Werksformen{% endblock title %}
{% block head %}
<link type="text/css" rel="stylesheet" href="{{ url_for('static', filename='css/datatables.css') }}">
{% endblock head %}
{% block heading %}Werksformen{% endblock heading %}
{% block content %}
{% include "_icons.svg" %}
<table id="werksform-table">
<thead>
<tr>
<th>Werksformen</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
<tbody>
{% for werksform in werksformen %}
<tr id="werksform-{{ werksform['ID'] }}">
<td title="Werksform">{{ werksform["Werksform"] }}</td>
<td class="action action-update" data-id="{{ werksform['ID'] }}" data-werksform="{{werksform['Werksform'] }}"><a href="#" title="Werksform bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ werksform['ID'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('werksform.delete', id=werksform['ID']) }}" title="Werksform löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
<dialog aria-labelledby="dialog-heading" id="werksform-modal">
<article>
<form id="werksform_detail_form" method="dialog" >
<header>
<button class="modal-close" aria-label="close" rel="prev" formnovalidate></button>
<h1 id="dialog-heading">#</h1>
</header>
<fieldset>
<article>
<label>
<span class="required">Werksform</span>
<input id="form_Werksform" name="form_Werksform" aria-Label="Werksform" required autofocus/>
</label>
</article>
</fieldset>
<footer class="grid">
<button id="form_submit" type="submit" formmethod="post" formaction="#">OK</button>
<button class="secondary" aria-label="close" formmethod="dialog" formnovalidate>Abbrechen</button>
</footer>
</form>
</article>
</dialog>
{% endblock content %}
{% block script %}
<script src="{{ url_for('static', filename='js/datatables.js') }}"></script>
<script src="{{ url_for('static', filename='js/init_dt.js') }}"></script>
<script src="{{ url_for('static', filename='js/modal.js') }}"></script>
<script>
window.onload = function () {
initDataTable("werksform-table");
initCreateButton("werksform-table", "Werksform hinzufügen …");
initModal("werksform-modal", "form_Werksform", ["Neue Werksform", "Werksform bearbeiten"], ["{{ url_for('werksform.create') }}", "{{ url_for('werksform.update', id=-1) }}"]);
}
</script>
{% endblock script %}

View File

@ -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/<int:id>", 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/<int:id>")
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))

65
the_works/views/view.py Normal file
View File

@ -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": "/<int:id>"},
{"name": "delete", "route_params": "/<int:id>"}
]
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"))

View File

@ -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/<int:id>", 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/<int:id>")
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"))