Genres can now be added, changed, and removed to/from Werk entries

This commit is contained in:
eclipse 2025-05-08 09:47:20 +02:00
parent 0fe1c54d9d
commit 9610915b19
4 changed files with 77 additions and 41 deletions

View File

@ -17,7 +17,8 @@ class Werk(db.Model):
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")
werk_genre = relationship("Werk_Genre", back_populates="werk", cascade="save-update, merge, delete, delete-orphan")
genres = association_proxy("werk_genre", "Genre")
class Veroeffentlichung(db.Model):
__table__ = db.Model.metadata.tables['Veroeffentlichung']
@ -73,3 +74,6 @@ class Werk_Genre(db.Model):
werk = relationship("Werk", back_populates="werk_genre")
genre = relationship("Genre", back_populates="werk_genre")
def __init__(self, genre: int):
self.Genre = genre

View File

@ -1,4 +1,5 @@
{% extends 'base.html' %}
{% set SPLIT_CHARACTER = ", " %}
{% block title %}Werke{% endblock title %}
@ -12,7 +13,7 @@
});
deRole("#werk-table");
// create "New"-button and append it to the <div> containing the DataTables search field
// create "New"-element and append it to the <div> containing the DataTables search field
let a = document.createElement("a");
a.id = "create-button";
a.setAttribute("title", "Werk hinzufügen");
@ -38,6 +39,7 @@
<th>Reihe</th>
<th>Verlag</th>
<th>Werksform</th>
<th>Genre(s)</th>
<th colspan="2">Aktionen</th>
</tr>
</thead>
@ -49,10 +51,11 @@
<td title="Reihe">{{ werk["Reihe"] }}</td>
<td title="Verlag">{{ werk["Verlag"] }}</td>
<td title="Werksform">{{ werk["Werksform"] }}</td>
<td title="Genres">{{ werk["Genre_list"] | join(SPLIT_CHARACTER) }}</td>
<td class="action action-update" data-id="{{ werk['id'] }}"><a href="{{ url_for('werk.read', id=werk['id']) }}" title="Werk ansehen/bearbeiten"><svg viewbox="0 0 24 24"><use href="#update" /></svg></a></td>
<td id="delete-{{ werk['id'] }}" class="action"><a onclick="return confirm('Eintrag wirklich löschen?');" href="{{ url_for('werk.delete', id=werk['id']) }}" title="Werk löschen"><svg viewbox="0 0 24 24"><use href="#delete" /></svg></a></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}
{% endblock content %}

View File

@ -47,12 +47,15 @@ Werk bearbeiten
{% block content %}
<form id="werk_detail_form" method="post" enctype="multipart/form-data" action="#">
<div class="grid">
<section>
<label>
<span class="required">Titel</span>
<input id="form_Titel" name="form_Titel" aria-label="Titel" placeholder="Titel" required value="{{ werk['Titel'] }}" />
</label>
</section>
<hr />
<section class="grid">
<div>
<label>
<span class="required">Titel</span>
<input id="form_Titel" name="form_Titel" aria-label="Titel" placeholder="Titel" required value="{{ werk['Titel'] }}" />
</label>
<label>
Untertitel
<input id="form_Untertitel" name="form_Untertitel" aria-label="Untertitel" placeholder="Untertitel" value="{{ werk['Untertitel'] }}" />
@ -64,31 +67,16 @@ Werk bearbeiten
{% for wf in werksformen %}<option value="{{ wf.ID }}"{% if wf.ID == werk['Werksform'] %} selected{% endif %}>{{ wf.Werksform }}</option>{% endfor %}
</select>
</label>
<div class="grid">
<label>
Reihe
<select id="form_Reihe" name="form_Reihe" aria-label="Der Text gehört zur Reihe …">
<option value="" >keine Reihe</option>
{% for r in reihen %}<option value="{{ r.ID }}"{% if r.ID == werk['Reihe'] %} selected{% endif %}>{{ r.Titel }}</option>{% endfor %}
</select>
</label>
<label>
Reihennummer
<input id="form_Reihennummer" name="form_Reihennummer" aria-label="Reihennummer" placeholder="keine Reihennummer" value="{{ werk['Reihennummer'] }}" />
</label>
</div>
<label>
Verlag
<select id="form_Verlag" name="form_Verlag" aria-label="Verlag">
<option selected value="">kein Verlag</option>
{% for v in verlage %}<option value="{{ v.ID }}"{% if v.ID == werk['Verlag'] %} selected{% endif %}>{{ v.Verlag }}</option>{% endfor %}
Reihe
<select id="form_Reihe" name="form_Reihe" aria-label="Der Text gehört zur Reihe …">
<option value="" >keine Reihe</option>
{% for r in reihen %}<option value="{{ r.ID }}"{% if r.ID == werk['Reihe'] %} selected{% endif %}>{{ r.Titel }}</option>{% endfor %}
</select>
</label>
</div>
<div>
<label>
Preis
<input id="form_Preis" name="form_Preis" aria-label="Preis" placeholder="kein Preis" value="{{ werk['Preis'] }}" />
Reihennummer
<input id="form_Reihennummer" name="form_Reihennummer" aria-label="Reihennummer" placeholder="keine Reihennummer" value="{{ werk['Reihennummer'] }}" />
</label>
<label>
Erscheinungsdatum (TT-MM-JJJJ, MM-JJJJ, JJJJ oder leer)
@ -98,6 +86,19 @@ Werk bearbeiten
<input type="number" min="1980" max="2100" id="form_Erscheinungsjahr" name="form_Erscheinungsjahr" aria-label="Erscheinungsjahr" placeholder="Jahr" value="{{ werk['Erscheinungsdatum'][:4] }}" />
</div>
</label>
</div>
<div>
<label>
Verlag
<select id="form_Verlag" name="form_Verlag" aria-label="Verlag">
<option selected value="">kein Verlag</option>
{% for v in verlage %}<option value="{{ v.ID }}"{% if v.ID == werk['Verlag'] %} selected{% endif %}>{{ v.Verlag }}</option>{% endfor %}
</select>
</label>
<label>
Preis
<input id="form_Preis" name="form_Preis" aria-label="Preis" placeholder="kein Preis" value="{{ werk['Preis'] }}" />
</label>
<label>
ISBN-13
<input id="form_ISBN_13" name="form_ISBN_13" aria-label="ISBN-13" placeholder="keine ISBN-13" value="{{ werk['ISBN_13'] }}" />
@ -111,8 +112,19 @@ Werk bearbeiten
<input id="form_ISSN" name="form_ISSN" aria-label="ISSN" placeholder="keine ISSN" value="{{ werk['ISSN'] }}" />
</label>
</div>
</div>
<div class="grid">
</section>
<hr />
<section>
<fieldset>
<legend>Genre(s)</legend>
{% for g in genres %}
<input id="form_Genres_{{ g.ID }}" name="form_Genres" type="checkbox" value="{{ g.ID }}" {% if g.ID in werk["Genres"] %} checked {% endif %}/>
<label for="form_Genres_{{ g.ID }}">{{ g.Genre }}</label>
{% endfor %}
</fieldset>
</section>
<hr />
<section class="grid">
<label>
Klappentext
<textarea id="form_Klappentext" name="form_Klappentext" aria-label="Klappentext" placeholder="kein Klappentext" rows="10">{{ werk['Klappentext'] }}</textarea>
@ -122,13 +134,15 @@ Werk bearbeiten
<textarea id="form_Anmerkungen" name="form_Anmerkungen" aria-label="Anmerkungen" placeholder="keine Anmerkungen" rows="10">
{{ werk['Anmerkungen'] }}</textarea>
</label>
</div>
<div>
</section>
<hr />
<section>
<label>
Titelbild
<input type="file" id="form_Titelbild" name="form_Titelbild" aria-label="Titelbild" placeholder="kein Titelbild" />
</label>
</div>
</section>
<footer class="grid">
<button id="form_submit" type="submit" onclick="return validate_date()" formmethod="post" formaction="{% if create_mode %}{{ url_for('werk.create') }}{% else %}{{ url_for('werk.update', id=werk['ID']) }}{% endif %}">
{% if create_mode %}Eintrag speichern{% else %}Änderungen speichern{% endif %}

View File

@ -1,7 +1,7 @@
from flask import Blueprint, render_template, request, redirect, flash, url_for
from sqlalchemy import select, insert, update, delete
from the_works.database import db
from the_works.models import Werk, Reihe, Verlag, Werksform
from the_works.models import Werk, Reihe, Verlag, Werksform, Werk_Genre, Genre
bp = Blueprint("werk", __name__)
@ -22,7 +22,9 @@ def all():
"Verlag": row.Verlag.Verlag if row.Verlag else "",
"v_id": row.Werk.Verlag or "",
"Reihe": row.Reihe.Titel if row.Reihe else "",
"r_id": row.Werk.Reihe or ""
"r_id": row.Werk.Reihe or "",
"Genre_list": [wg.genre.Genre for wg in row.Werk.werk_genre],
"g_id_list": row.Werk.genres
})
return render_template("views/werk.html", werke=werke)
@ -30,7 +32,7 @@ def all():
def read(id):
# id of zero -> create new entry
if id == 0:
return render_template("views/werk_detail.html", werk={"ID": 0, "Erscheinungsdatum": ""}, reihen=db.session.scalars(select(Reihe)), verlage=db.session.scalars(select(Verlag)), werksformen=db.session.scalars(select(Werksform)))
return render_template("views/werk_detail.html", werk={"ID": 0, "Erscheinungsdatum": ""}, reihen=db.session.scalars(select(Reihe)), verlage=db.session.scalars(select(Verlag)), werksformen=db.session.scalars(select(Werksform)), genres=db.session.scalars(select(Genre)))
# all other ids -> update existing entry
w = db.session.get(Werk, id)
werk = {
@ -48,13 +50,14 @@ def read(id):
"Preis": w.Preis or "",
"Titelbild": "",
"Klappentext": w.Klappentext or "",
"Anmerkungen": w.Anmerkungen or ""
"Anmerkungen": w.Anmerkungen or "",
"Genres": w.genres
}
return render_template("views/werk_detail.html", werk=werk, reihen=db.session.scalars(select(Reihe)), verlage=db.session.scalars(select(Verlag)), werksformen=db.session.scalars(select(Werksform)))
return render_template("views/werk_detail.html", werk=werk, reihen=db.session.scalars(select(Reihe)), verlage=db.session.scalars(select(Verlag)), werksformen=db.session.scalars(select(Werksform)), genres=db.session.scalars(select(Genre)))
@bp.route("/werk/create", methods=["POST"])
def create():
db.session.add(Werk(
werk = Werk(
Titel = request.form["form_Titel"],
Untertitel = request.form["form_Untertitel"] or None,
Werksform = request.form["form_Werksform"],
@ -69,7 +72,10 @@ def create():
Titelbild = None,
Klappentext = request.form["form_Klappentext"] or None,
Anmerkungen = request.form["form_Anmerkungen"] or None
))
)
for g in request.form.getlist("form_Genres"):
werk.genres.append(g)
db.session.add(werk)
db.session.commit()
flash("Eintrag erfolgreich hinzugefügt")
return redirect(url_for("werk.all"))
@ -78,6 +84,7 @@ def create():
def update(id):
# get record
werk = db.session.get(Werk, id)
# update values
werk.Titel = request.form["form_Titel"]
werk.Untertitel = request.form["form_Untertitel"] or None
@ -93,6 +100,14 @@ def update(id):
werk.Titelbild = None
werk.Klappentext = request.form["form_Klappentext"] or None
werk.Anmerkungen = request.form["form_Anmerkungen"] or None
# update genre list by removing genres not in form selection and adding selected ones not currently in list
form_set = set(map(lambda g: int(g), request.form.getlist("form_Genres")))
for g in set(werk.genres) - form_set:
werk.genres.remove(g)
for g in form_set - set(werk.genres):
werk.genres.append(g)
# commit changes
db.session.commit()
flash("Eintrag erfolgreich geändert")