commit 4b4a3fb56f0e7fbb4fa88c845352584ce091a757 Author: Albert Date: Sat Nov 8 23:25:18 2025 +0100 Initial project import: Flask app, templates, init script, README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..583b316 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Virtual environment +.venv/ + +# SQLite DB +anmeldung.db + +# Python caches +__pycache__/ +*.pyc + +# Editor settings +.vscode/ +.idea/ + +# OS files +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..cfb0e18 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Anmeldung_v2 + +Kleine Flask-Webapp, um einen papierbasierten Anmeldebogen durch ein Formular zu ersetzen und die Eingaben in einer SQLite-Datenbank zu speichern. + +Installieren: + +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +``` + +DB initialisieren und Beispiel-Fragen anlegen: + +```bash +python init_db.py +``` + +App starten: + +```bash +python app.py +``` + +Das Formular ist dann unter http://127.0.0.1:5000/ erreichbar. diff --git a/app.py b/app.py new file mode 100644 index 0000000..06cd6b1 --- /dev/null +++ b/app.py @@ -0,0 +1,116 @@ +from flask import Flask, render_template, request, redirect, url_for +from flask_sqlalchemy import SQLAlchemy +import os +import re + +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +DB_PATH = os.path.join(BASE_DIR, 'anmeldung.db') + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_PATH}' +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + +db = SQLAlchemy(app) + + +class Adresse(db.Model): + id = db.Column(db.Integer, primary_key=True) + vorname = db.Column(db.String(100), nullable=False) + nachname = db.Column(db.String(100), nullable=False) + strasse = db.Column(db.String(200), nullable=False) + hausnummer = db.Column(db.String(50), nullable=True) + plz = db.Column(db.String(20), nullable=False) + ort = db.Column(db.String(100), nullable=False) + land = db.Column(db.String(50), default='Deutschland') + telefon_vorwahl = db.Column(db.String(20)) + telefon_nummer = db.Column(db.String(50)) + email = db.Column(db.String(200)) + + +class Frage(db.Model): + id = db.Column(db.Integer, primary_key=True) + text = db.Column(db.String(500), nullable=False) + + +class Antwort(db.Model): + id = db.Column(db.Integer, primary_key=True) + adresse_id = db.Column(db.Integer, db.ForeignKey('adresse.id'), nullable=False) + frage_id = db.Column(db.Integer, db.ForeignKey('frage.id'), nullable=False) + text = db.Column(db.String(1000), nullable=True) + + +@app.route('/', methods=['GET', 'POST']) +def index(): + if request.method == 'POST': + # Adresse speichern + vorname = request.form.get('vorname', '').strip() + nachname = request.form.get('nachname', '').strip() + strasse = request.form.get('strasse', '').strip() + hausnummer = request.form.get('hausnummer', '').strip() + plz = request.form.get('plz', '').strip() + ort = request.form.get('ort', '').strip() + land = request.form.get('land', 'Deutschland').strip() + telefon_vorwahl = request.form.get('telefon_vorwahl', '').strip() + telefon_nummer = request.form.get('telefon_nummer', '').strip() + email = request.form.get('email', '').strip() + # server-side E-Mail Validierung (einfache Prüfung) + errors = {} + email_re = re.compile(r"[^@]+@[^@]+\.[^@]+") + if email: + if not email_re.match(email): + errors['email'] = 'Ungültige E-Mail-Adresse' + # PLZ Validierung: genau 5 Ziffern + if plz: + if not re.fullmatch(r"\d{5}", plz): + errors['plz'] = 'Postleitzahl muss genau 5 Ziffern haben' + + if errors: + fragen = Frage.query.all() + # pass form data back to template so fields are preserved + form = request.form.to_dict() + return render_template('index.html', fragen=fragen, errors=errors, form=form) + + adresse = Adresse( + vorname=vorname, + nachname=nachname, + strasse=strasse, + hausnummer=hausnummer, + plz=plz, + ort=ort, + land=land, + telefon_vorwahl=telefon_vorwahl, + telefon_nummer=telefon_nummer, + email=email, + ) + db.session.add(adresse) + db.session.commit() + + # Antworten speichern + fragen = Frage.query.all() + for frage in fragen: + key = f'frage_{frage.id}' + antwort_text = request.form.get(key, '').strip() + antwort = Antwort(adresse_id=adresse.id, frage_id=frage.id, text=antwort_text) + db.session.add(antwort) + db.session.commit() + + # Nach erfolgreichem Speichern weiterleiten + return redirect(url_for('danke', id=adresse.id)) + + # GET: Formular anzeigen + fragen = Frage.query.all() + return render_template('index.html', fragen=fragen) + + +@app.route('/danke') +def danke(): + id = request.args.get('id') + adresse = Adresse.query.get(id) + return render_template('danke.html', adresse=adresse) + + +if __name__ == '__main__': + # Ensure DB exists + if not os.path.exists(DB_PATH): + db.create_all() + app.run(debug=True) diff --git a/init_db.py b/init_db.py new file mode 100644 index 0000000..3c66517 --- /dev/null +++ b/init_db.py @@ -0,0 +1,24 @@ +from app import app, db, Frage + + +def init_db(): + # Ensure we run DB commands inside the Flask application context + with app.app_context(): + db.drop_all() + db.create_all() + + sample = [ + 'Haben Sie besondere Ernährungsbedürfnisse?', + 'Benötigen Sie eine Übernachtung?', + 'Möchten Sie unseren Newsletter erhalten?' + ] + for text in sample: + f = Frage(text=text) + db.session.add(f) + db.session.commit() + + print('DB initialisiert und Beispiel-Fragen angelegt.') + + +if __name__ == '__main__': + init_db() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..4d1cadb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +Flask>=2.0 +Flask-SQLAlchemy>=3.0 diff --git a/templates/danke.html b/templates/danke.html new file mode 100644 index 0000000..3985deb --- /dev/null +++ b/templates/danke.html @@ -0,0 +1,17 @@ + + + + + Danke + + +

Danke für Ihre Anmeldung

+ {% if adresse %} +

Vielen Dank, {{ adresse.vorname }} {{ adresse.nachname }}. Ihre Daten wurden gespeichert.

+

Adresse: {{ adresse.strasse }}{% if adresse.hausnummer %} {{ adresse.hausnummer }}{% endif %}, {{ adresse.plz }} {{ adresse.ort }}

+ {% else %} +

Eintrag gespeichert.

+ {% endif %} +

Zurück zum Formular

+ + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..d159c3b --- /dev/null +++ b/templates/index.html @@ -0,0 +1,40 @@ + + + + + + Anmeldebogen + + + +

Anmeldebogen

+
+
+ Persönliche Daten + + + + + + + + + + +
+ + {% if fragen %} +
+ Fragen + {% for frage in fragen %} + + {% endfor %} +
+ {% endif %} + +

+
+ +