From 6ee0f9ea9dea2f46b3d9c79c6a2fd26887aea4e1 Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 12 Jun 2026 10:38:58 +0000 Subject: [PATCH 1/6] README.md aktualisiert --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 089bb04..79dce62 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,15 @@ Muster-Implementation durch die Lehrkraft in python3 mit Django ## To get started +## Vorbereitung der virtuellen Entwicklungsumgebung + +in einem Projekt-Vezeichnis über dem eigentlichen SGTMensa-Projekt-Ordner + ```bash -cd SGTMensa python3 -m venv .venv source .venv/bin/activate pip install django -django-admin startproject mensa-core . +pip install pillow ``` Falls eine fish-Shell vorliegt: @@ -19,7 +22,7 @@ Falls eine fish-Shell vorliegt: python3 -m venv .venv source .venv/bin/activate.fish pip install django -django-admin startproject mensa-core . +pip install pillow ``` ### Schritt 1: Die Arbeitsumgebung isolieren (Virtual Environment) @@ -42,9 +45,10 @@ Installiere nur das Nötigste. Für den Start reicht Django. ```bash pip install django +pip install pillow ``` -### Schritt 3: Das Projekt initialisieren +### Schritt 3: Das Projekt initialisieren (nur einmalig, beim ersten Start des Projekts) Erstelle die Struktur eines Django-Projekts. -- 2.52.0 From eac2457a064882afc5c3dd82654310c24947ad1d Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 12 Jun 2026 10:41:57 +0000 Subject: [PATCH 2/6] README.md aktualisiert --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 79dce62..79142f4 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,24 @@ pip install django pip install pillow ``` +## Klonen des eigentlichen Projekts + +```bash +git clone https://git.sgtlernen.de/mputzlocher/SGTMensa.git +``` + +## Starten des Servers + +```bash +cd SGTMensa +python manage.py runserver +``` + + +--- + +# Erweiterte Erklärung einzelner Schritte + ### Schritt 1: Die Arbeitsumgebung isolieren (Virtual Environment) Bevor du auch nur eine Zeile Code schreibst, erstelle eine eigene Umgebung. Das verhindert, dass sich verschiedene Projekte auf deinem Rechner gegenseitig stören. -- 2.52.0 From 5d060587cbe8e83c0fbdccc36cb978e52fa4b66d Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 12 Jun 2026 12:51:27 +0200 Subject: [PATCH 3/6] =?UTF-8?q?Datenbank=20wieder=20verf=C3=BCgbar=20gemac?= =?UTF-8?q?ht=20f=C3=BCr=20Testdaten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - db.sqlite3 | Bin 0 -> 241664 bytes 2 files changed, 1 deletion(-) create mode 100644 db.sqlite3 diff --git a/.gitignore b/.gitignore index 9031276..41e951a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ __pycache__/ *.pyc -*.sqlite3 diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..99587ffd9c4ef5b99d7bcef6693ebd5cdd756152 GIT binary patch literal 241664 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 Xb&m=$Ug5| Date: Thu, 25 Jun 2026 08:59:15 +0200 Subject: [PATCH 4/6] =?UTF-8?q?kleine=20=C3=84nderungen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ns_alter_gericht_time_creation_and_more.py | 38 +++++++++++++++++++ mensa_app/models.py | 4 +- mensa_app/urls.py | 1 + mensa_app/views.py | 1 + 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 mensa_app/migrations/0011_alter_person_options_alter_gericht_time_creation_and_more.py diff --git a/mensa_app/migrations/0011_alter_person_options_alter_gericht_time_creation_and_more.py b/mensa_app/migrations/0011_alter_person_options_alter_gericht_time_creation_and_more.py new file mode 100644 index 0000000..81d30d5 --- /dev/null +++ b/mensa_app/migrations/0011_alter_person_options_alter_gericht_time_creation_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.2.15 on 2026-06-12 10:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mensa_app', '0010_merge_20260612_0913'), + ] + + operations = [ + migrations.AlterModelOptions( + name='person', + options={}, + ), + migrations.AlterField( + model_name='gericht', + name='time_creation', + field=models.TimeField(default=datetime.datetime(2026, 6, 12, 10, 50, 49, 206132)), + ), + migrations.AlterField( + model_name='gericht', + name='time_last_change', + field=models.TimeField(default=datetime.datetime(2026, 6, 12, 10, 50, 49, 206132)), + ), + migrations.AlterField( + model_name='gerichtbild', + name='id', + field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + migrations.AlterField( + model_name='person', + name='rolle', + field=models.CharField(choices=[('schueler', 'Schüler'), ('eltern', 'Eltern'), ('lehrer', 'Lehrer'), ('mitarbeiter', 'Mensa-Mitarbeiter'), ('chef', 'Mensa-Leitung')], max_length=20), + ), + ] diff --git a/mensa_app/models.py b/mensa_app/models.py index 88062d2..fb88a67 100644 --- a/mensa_app/models.py +++ b/mensa_app/models.py @@ -1,10 +1,8 @@ +import os from django.db import models from django.contrib.auth.models import User from django.utils import timezone import datetime - -import os -from django.db import models from django.core.exceptions import ValidationError from django.core.validators import FileExtensionValidator # Pillow ist für die Bildbearbeitung zuständig (installiere per pip install pillow) diff --git a/mensa_app/urls.py b/mensa_app/urls.py index c59a541..0a3ecbe 100644 --- a/mensa_app/urls.py +++ b/mensa_app/urls.py @@ -7,4 +7,5 @@ urlpatterns = [ path('speisekarte/', GerichtListView.as_view(), name='speisekarte'), path('speiseplan/', SpeiseplanView.as_view(), name='speiseplan'), path('bestellungen/summary/', BestellSummaryView.as_view(), name='bestell_summary'), + path('userlist/', {},"" ), ] diff --git a/mensa_app/views.py b/mensa_app/views.py index 662af6f..ba9d79d 100644 --- a/mensa_app/views.py +++ b/mensa_app/views.py @@ -36,6 +36,7 @@ class SpeiseplanView(TemplateView): context['target_date'] = target_date context['menues_day'] = Menue.objects.filter(tag__datum=target_date) + # 3. Dauerangebote laden (unabhängig vom Tag) context['dauerangebote'] = Gericht.objects.filter(ist_dauerangebot=True) -- 2.52.0 From d7461cb7d2de2e441f75578b1d1052a35f09605a Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Thu, 25 Jun 2026 07:10:32 +0000 Subject: [PATCH 5/6] README.md aktualisiert MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anleitung für die Entwicklungsarbeit ergänzt --- README.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 79142f4..41e75a7 100644 --- a/README.md +++ b/README.md @@ -140,4 +140,71 @@ python manage.py runserver -Öffne deinen Browser unter `http://127.0.0.1:8000/admin`. Logge dich mit deinem Superuser ein. **Herzlichen Glückwunsch!** Du hast eine voll funktionsfähige Web-Anwendung, mit der du bereits Speisepläne und Bestellungen in einer Datenbank verwalten kannst. \ No newline at end of file +Öffne deinen Browser unter `http://127.0.0.1:8000/admin`. Logge dich mit deinem Superuser ein. **Herzlichen Glückwunsch!** Du hast eine voll funktionsfähige Web-Anwendung, mit der du bereits Speisepläne und Bestellungen in einer Datenbank verwalten kannst. + + +### Schritt 9: Eigentliche Entwicklungsarbeit + +Folgende Befehle werden nacheinander ausgeführt: + +#### Eigenen Projektbaum auf dem lokalen Rechen auf den aktuellen Stand bringen + +Öffne ein Terminal und navigiere in das Projektverzeichnis, das bereits über `git clone` abgeholt worden ist. + +zum Beispiel: +```bash +cd ~/projects/SGTMensa +``` + +Hole den aktuellen Stand ab: +```bash +git pull +``` + +Aktiviere die virtuelle Entwicklungsumgebung (falls noch nicht geschehen): +```bash +source .venv/bin/activate +``` + +Führe notwendige Migrationen der bestehenden Datenbank aus: +```bash +python manage.py makemigrations +python manage.py migrate +``` + +Starte den Server des Projekts: +```bash +python manage.py runserver +``` +Jetzt bist Du startklar für die Entwicklungsarbeit und solltest den aktuellen Stand im Browser unter `http://localhost:8000/` abrufen können. + +#### Änderungen vornehmen + +Django erkennt selbstständig Veränderungen am Quellcode und startet den Webserver neu. Achte auf Fehlermeldungen! + +#### Änderungen wieder auf den git-Server einspielen + +Nach einem Entwicklungsschritt solltest Du Deine Änderungen von Deinem lokalen Rechner wieder auf den git-Server hochladen, +damit Dein Team auch sieht, was Du gemacht hast, und damit Deine Ergänzungen und Änderungen wieder in den gemeinsamen +Code integriert werden können. + +Nachsehen der Änderungen: +```bash +git status +``` +Dies zeigt alle veränderten Dateien an. + +Veränderte Dateien ins Änderungspaket aufnehmen: +```bash +git add . +``` + +Veränderungen bestätigen und beschreiben: +```bash +git commit -m "Deine sinnvolle Beschreibung der Änderung in wenigen Worten" +``` + +Veränderungen auf den git-Server hochladen: +```bash +git push +``` -- 2.52.0 From 40bd15f37829936f5beaa5508f1dc3f252574a24 Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 26 Jun 2026 09:29:22 +0200 Subject: [PATCH 6/6] =?UTF-8?q?Vorbereitung=20f=C3=BCr=20Erfassung=20neuer?= =?UTF-8?q?=20Gerichte?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mensa_app/forms.py | 33 ++++++++++++ mensa_app/models.py | 1 + .../templates/mensa_app/add_gericht.html | 32 +++++++++++ .../mensa_app/add_gericht_success.html | 29 ++++++++++ mensa_app/urls.py | 17 +++++- mensa_app/views.py | 54 ++++++++++++++----- 6 files changed, 152 insertions(+), 14 deletions(-) create mode 100644 mensa_app/forms.py create mode 100644 mensa_app/templates/mensa_app/add_gericht.html create mode 100644 mensa_app/templates/mensa_app/add_gericht_success.html diff --git a/mensa_app/forms.py b/mensa_app/forms.py new file mode 100644 index 0000000..d9bcac4 --- /dev/null +++ b/mensa_app/forms.py @@ -0,0 +1,33 @@ +# forms.py + +from django import forms +from .models import Gericht +# Importiere alle Modelle, die für das Formular relevant sind +from .models import Kategorie + +class GerichtForm(forms.ModelForm): + """Definiert die Struktur und Validierungsregeln für das Gericht-Modell.""" + + class Meta: + model = Gericht + fields = [ + 'name', + 'kategorie', + 'preis', + 'ist_vegetarisch', + 'ist_allergene_frei', + 'allergene', + 'beschreibung', # Neues Feld für Zutaten/Rohstoffe + 'bilder', # Das Bild-Feld + 'ist_dauerangebot' + ] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Wir können hier zusätzliche Validierungen oder Widgets einbinden + # Beispiel: Erzwinge das Betreten der Kategorie-Auswahl + self.fields['kategorie'].required = True + + # Hier könntest du auch einen Fallback für den Preis hinzufügen, falls er nicht gesetzt ist + if 'initial' in kwargs: # Wird bei GET-Requests genutzt + self.initial['preis'] = 0.00 diff --git a/mensa_app/models.py b/mensa_app/models.py index fb88a67..d99ca4b 100644 --- a/mensa_app/models.py +++ b/mensa_app/models.py @@ -128,6 +128,7 @@ class Gericht(models.Model): ) ist_vegetarisch = models.BooleanField(default=False) ist_allergene_frei = models.BooleanField(default=False) + beschreibung = models.TextField(blank=True, null=True) # Zutaten/Rohstoffe Beschreibung (Textfeld für V1) allergene = models.TextField(blank=True, default="") preis = models.DecimalField(max_digits=5, decimal_places=2, default=0.00) diff --git a/mensa_app/templates/mensa_app/add_gericht.html b/mensa_app/templates/mensa_app/add_gericht.html new file mode 100644 index 0000000..f89c48e --- /dev/null +++ b/mensa_app/templates/mensa_app/add_gericht.html @@ -0,0 +1,32 @@ + + + + + + +
+

Neue Speiseart hinzufügen

+ + {# !!! KRITISCH WICHTIG: enctype muss für Dateiuploads stehen !!! #} +
+ {% csrf_token %} + + + {# Man kann die komplexe Struktur durch eine einfache Schleife ersetzen #} + {% for field in form %} +
+ + {{ field }} + + + {% if field.errors %} +

{{ field.errors }}

+ {% endif %} +
+ {% endfor %} + + +
+
+ + diff --git a/mensa_app/templates/mensa_app/add_gericht_success.html b/mensa_app/templates/mensa_app/add_gericht_success.html new file mode 100644 index 0000000..72f716c --- /dev/null +++ b/mensa_app/templates/mensa_app/add_gericht_success.html @@ -0,0 +1,29 @@ + + + + + Erfolg + + + + +
+
+

🎉 Erfolgreich hinzugefügt! 🎉

+

+ Das Gericht {{ objekt_name }} wurde erfolgreich in das Menüsystem übernommen. +

+

+ Du kannst nun die Details überprüfen und weitere Gerichte hinzufügen. +

+
+ + +
+ + diff --git a/mensa_app/urls.py b/mensa_app/urls.py index 0a3ecbe..49ea019 100644 --- a/mensa_app/urls.py +++ b/mensa_app/urls.py @@ -7,5 +7,20 @@ urlpatterns = [ path('speisekarte/', GerichtListView.as_view(), name='speisekarte'), path('speiseplan/', SpeiseplanView.as_view(), name='speiseplan'), path('bestellungen/summary/', BestellSummaryView.as_view(), name='bestell_summary'), - path('userlist/', {},"" ), +] + +# ACHTUNG: Hier benötigen wir jetzt eine separate View für die Erfolgsmeldung! +# Wir nutzen hierfür ein sehr einfaches TemplateView. +from django.views.generic import TemplateView # Muss oben importiert werden +from .models import Gericht + +class ErfolgTemplateView(TemplateView): + """Zeigt einfach nur die Bestätigung an.""" + template_name = 'mensa_app/add_gericht_success.html' + +urlpatterns += [ + # ... (vorherige Pfade bleiben) ... + path('gerichte/neu/', GerichtCreateView.as_view(), name='add_gericht'), + # NEU: Erfolgsmeldung nach erfolgreichem POST/redirect + path('erfolg/', ErfolgTemplateView.as_view(), name='success_message'), ] diff --git a/mensa_app/views.py b/mensa_app/views.py index ba9d79d..f5b1658 100644 --- a/mensa_app/views.py +++ b/mensa_app/views.py @@ -1,18 +1,20 @@ +# views.py +from django.db.models import Count, Sum from django.shortcuts import render +from django.utils import timezone +from datetime import datetime +from django.views.generic import ListView, TemplateView +from django.views.generic.edit import CreateView +from django.shortcuts import redirect # Importiere die Redirect-Funktion +from .forms import GerichtForm # Importiere dein neues Formular +from .models import Gericht, Menue, SpeiseplanTag, Bestellung -# Create your views here. -from django.views.generic import ListView -from .models import Gericht class GerichtListView(ListView): model = Gericht template_name = 'mensa_app/gericht_liste.html' # Der Pfad zum Template context_object_name = 'alle_gerichte' # Der Name, den wir im Template nutzen -from django.views.generic import TemplateView -from django.utils import timezone -from datetime import datetime -from .models import Menue, Gericht, SpeiseplanTag class SpeiseplanView(TemplateView): template_name = 'mensa_app/speiseplan.html' @@ -51,12 +53,6 @@ class SpeiseplanView(TemplateView): return context -from django.views.generic import TemplateView -from django.utils import timezone -from django.db.models import Count, Sum -from datetime import datetime -from .models import Bestellung, SpeiseplanTag, Gericht, Menue - class BestellSummaryView(TemplateView): template_name = 'mensa_app/bestell_summary.html' @@ -100,3 +96,35 @@ class BestellSummaryView(TemplateView): context['total_umsatz'] = Bestellung.objects.filter(menue__tag__datum=target_date).aggregate(Sum('menue__preis'))['menue__preis__sum'] or 0 return context + +class GerichtCreateView(CreateView): + """ + View zur Erstellung eines neuen Gerichts. + Nutzt das benutzerdefinierte GerichtForm für die gesamte Steuerung. + """ + model = Gericht + form_class = GerichtForm # Verwendet unser Custom-Formular + template_name = 'mensa_app/add_gericht.html' + + def get_success_url(self): + # Die Methode wird ausgeführt, nachdem die View erfolgreich ist + objekt = self.object # Gibt uns das gerade gespeicherte Objekt zurück + return reverse('speisekarte') + + def form_valid(self, form): + """ + Übersteuert die Standard-Logik: + 1. Speichert zuerst das Gericht (über super()). + 2. Leitet danach auf ein success/confirmation Pattern um. + """ + super().form_valid() # Das eigentliche Speichern des Objekts + + # Hier ist der Haken an Django: Die View wird beim Erfolg automatisch weitergeleitet. + # Wir verwenden einen kleinen Trick, damit wir den Namen im Kontext haben. + + return redirect('success_nach_gerichterstellung') # Leiten auf eine temporäre URL um + + # Optional: Setzen des initialen Datenzustands (z.B. Datum, falls relevant) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + return context -- 2.52.0