Juntagrico ist in python geschrieben und verwendet das Web-Framework django. Dieses erlaubt es, Juntagrico mit wenig Aufwand an die eigenen Bedürfnisse anzupassen. Dafür ist ein grundlegendes Verständnis von python/django nötig, weshalb der Verein Juntagrico für die IT-Menschen der Juntanauten und allen interessierten einen Kurs anbietet.
Die Kurstermine werden via Openki bekanntgegeben und die Einschreibung erfolgt ebenfalls hier.
Die Zusammenfassung der Kurse können hier nachgelesen werden. Es folgen die Inhalte des ersten Kurses zur Einrichtung der Entwicklungsumgebung und zur Orientierung in django.
Inhalt dieses Kurses
In diesem ersten Teil, werden wir ein Django Projekt und ein Django App von Grund auf neu erstellen und lernen dessen wichtigsten Bestandteile an Beispielen kennen.
Installation
PyCharm
In diesem Kurs wird PyCharm Community Edition als Entwicklungsumgebung (IDE) genutzt. Du kannst aber auch eine andere IDE deiner Wahl nutzen, welches Python unterstützt.
In der Kostenpflichtigen Pro Version gibt es zusätzliche Funktionen, die die Handhabung von Django-Projekten vereinfacht. Wir starten hier ohne diesen Luxus.
Ich nehme an du weisst, wie du ein Programm in deinem Betriebssystem installierst.
PyCharm Community Edition (Du musst etwas runter-scrollen auf die dunkle Seite 😉)
Python
Wenn du PyCharm öffnest und du python nicht schon installiert hast, wird es dich fragen ob du es installieren willst. Klicke Ja.
Alternativ kannst du python auch manuell installieren.
https://www.python.org/downloads/
Starte danach deine IDE neu.
PyCharm Projekt und Virtuelle Umgebung erstellen
Python wird zusammen mit dem package manager pip installiert. Mit diesem können ganz einfach python packages aus dem Python Package Index pypi.org heruntergeladen und installiert werden.
Sobald wir an mehreren Projekten arbeiten, möchten wir sicherstellen, dass die Installierten python packages nicht in Konflikt zueinander stehen. Deshalb erzeugen wir für jedes Projekt an dem wir arbeiten eine virtuelle Umgebung (Virtual Environment). Z.B. mit Virtualenv. In diesem werden die packages separat installiert und bleiben isoliert.
PyCharm fragt beim Erstellen eines neuen Projekts gleich, ob es eine virtuelle Umgebung erstellen soll. Die Standardeinstellung passt.


Django
Django ist ein python package. Das heisst wir können es nun mit pip installieren.
Öffne dazu das Terminal im PyCharm (unten links) und führe folgendes aus:
python -m pip install Django

Damit haben wir alles installiert, was wir brauchen um ein Django Projekt zu erstellen.
Ein Django Projekt erstellen
Um ein leeres django Projekt zu erzeugen verwende folgenden Befehl, wobei du anstelle von mysite auch einen kreativeren Namen für dein Projekt wählen kannst.
django-admin startproject mysite
… Bild von Ordner Struktur
settings.py
In dieser Datei kannst du die grundlegende Einstellungen deines Django Projekts ändern. Es lohnt sich, dich mit den hier vorhandenen Einstellungen vertraut zu machen. Sie geben auch einen guten ersten Einblick in die Grundbausteine von django.
Die Settings die in Django geändern werden können sind ausführlich dokumentiert.
Django Apps, wie Juntagrico, können weitere Settings definieren. Dazu ein andermal mehr.
SECRET_KEY
Diese möglichst lange, zufällige Zeichenkette wird für kryptografische Signierungen verwendet. Wir müssen nur wissen, dass, wie der Name schon sagt, diesen Wert in der Produktionsumgebung geheim gehalten werden muss. Während wir entwickeln, kann uns das egal sein.
DEBUG
Mit dieser Einstellung entscheiden wir, ob wir die Debugging-Funktionen von Django einschalten wollen. Während wir entwickeln, wollen wir das natürlich einschalten. Dadurch zeigt Django hilfreiche Fehlermeldungen an statt nur eine Seite mit einem „500“ Fehler. Später, in der Produktiven Umgebung, müssen wir dies aus Sicherheitsgründen ausschalten.
ALLOWED_HOSTS
Dies ist wieder ein Setting für die Sicherheit. Solange DEBUG=True ist können wir das Setting leer lassen. In der Produktions-Umgebung müssen hier die Domains (oder IPs) gesetzt werden, über welche die Seite erreichbar sein darf.
INSTALLED_APPS
Ein Django Projekt baust du dir aus „Apps“ zusammen. Dazu später mehr. Mit dieser Einstellung werden die Apps aktiviert. Bereits aktiviert sind apps für die Authentifizierung, etc.
MIDDLEWARE
Hier werden Funktionen aktiviert, die dann im Hintergrund bestimmte Funktionalitäten hinzufügen. Bei einigen Apps erhältst du die Anweisung, hier einen Eintrag hinzuzufügen. Mehr müssen wir vorerst nicht wissen.
ROOT_URLCONF
In dieser Einstellung wird der Pfad zur url.py definiert, welche verwendet werden soll. Was diese Datei macht schauen wir uns gleich im Anschluss an.
TEMPLATES
Um das HTML für eine Webseite zu erzeugen werden „Templates“ verwendet, dazu später mehr. In dieser Einstellung wird bestimmt woher Templates geladen werden und womit sie „gerendert“ werden. Die Standardeinstellung passt für den Moment.
DATABASES
Hinter den Kulissen verwendet auch Django eine Datenbank um die dynamischen Daten der Webseite zu speichern. Unterstützt werden z.B. PostgreSQL, MySQL oder SQLite. Wir werden später sehen, dass Django die Datenbank so weit abstrahiert, dass es oft nicht relevant ist, welche Datenbank wir verwenden.
Diese Einstellung definiert die Zugangsinformationen zur Datenbank. Während der Entwicklung ist die vordefinierte SQLite Datenbank ganz nützlich. Wenn wir in die Produktionsumgebung wechseln brauchen wir dann aber etwas robusteres.
LANGUAGE_CODE
Django unterstützt natürlich mehrere (Menschen-)Sprachen und diverse lokale Formate, wie Datumsformate etc. Natürlich nur sofern die verwendeten Apps die gewünschten Übersetzungen auch mitliefern. Ändere den Wert hier z.B. auf "de-ch".
USE_I18N
Hiermit werden Übersetzungen gemäss obigem LANGUAGE_CODE aktiviert.
TIME_ZONE
Ein grosses Dankeschön geht an die Menschen, die sich mit Zeitzonen beschäftigen und dafür sorgen, das wir uns nicht darum sorgen müssen. Hier willst du die Zeitzone einstellen in der dein Projekt beheimatet ist. z.B. "Europe/Zurich". Spätestens bei der nächsten Zeitumstellung wirst du es merken, wenn du das vergisst.
USE_TZ
Hiermit aktivieren wir die Verwendung von Zeitzonen, was dringend empfohlen wird.
STATIC_URL
„Statische“ Dateien sind Bilder, CSS, Javascript etc. die unverändert zum Client geschickt werden. Mit diesem Setting definieren wir einen URL-prefix unter welchem solche Dateien später angeboten werden. Lasse hier am besten die Standardeinstellung und verwende „static/“ nicht für andere Zwecke.
urls.py
Genug Setting. Schauen wir mal in die urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
]
Es ist noch nicht so viel da. Aber wir sehen, dass die URL admin/ definiert wird. Diese werden wir gleich versuchen zu öffnen. Aber erst einmal müssen wir unseren Test-Server starten.
Den lokalen Server starten
runserver
Normalerweise laufen Webseites ja auf einem „Server“. Ein Server ist im wesentlichen nichts anderes als ein Computer mit einer schnellen Internetverbindung, irgendwo auf der Welt.
Während wir unser Django-Projekt entwickeln, können wir einfach unseren Computer als Server verwenden. Keine Sorge, solange du deine Firewall nicht absichtlich durchlöcherst, hast nur du Zugriff auf den lokalen Server.
Starte deinen lokalen Test-Server mit diesem Befehl im Terminal:
python manage.py runserver
Bis auf den roten Text You have 18 unapplied migration(s), sollte alles klappen und der Server läuft nun.
Automatischer Neustart
Füge als Test eine Leerzeile irgendwo in deine urls.py ein und speichere die Datei. Im Terminal wirst du sehen, wie der Server sich neu startet. Dies ist eine nützliche Funktion von Django, dass es den Test-Server automatisch neu startet, wenn wir eine Datei ändern. Dadurch können wir schneller testen, ob unsere Änderung funktioniert hat. Es gibt Fälle wo der automatische Neustart nicht funktioniert. Wir werden später in einen solchen rein laufen.
Configure Run
Damit wir den Server nicht aus dem Terminal starten müssen, können wir in PyCharm eine Konfiguration anlegen. Klicke dazu oben rechts auf Current File > Edit Configurations…

Danach auf das kleine + in der Ecke oben links > Python

Hier kannst du nun Einstellen, dass der runserver Befehl gestartet werden soll. Beachte, dass Working directory auf den Ordner zeigen muss wo die manage.py in deinem Projekt liegt.

Jetzt kannst du den Server mit einem Klick starten (vorher den Server im Terminal wieder stoppen)

Und wieder stoppen oder Neustarten

Mit dem Käfer können wir später die Debugging-Funktionen aktivieren. Dazu ein Andermal mehr.
Auf der Seite des Clients
Webseite öffnen
Genug Server. Schauen wir mal wie es auf der gegenüberliegenden Seite, der sogenannten Client-Seite, aussieht. Stell sicher, dass dein Server nun läuft. Dann öffne localhost auf dem Port 8000 im Browser, sprich, klicke hier:
Viola. Eine Rakete. Die Django-Entwickler:innen haben keine Mühen gescheut uns ein schnelles erstes Erfolgserlebnis zu ermöglichen.
Zum Verständnis: 127.0.0.1 ist die interne IP deines eigenen Computers und hier läuft dein Test-Server, der die Anfrage beantwortet und dir eine Webseite anzeigt. Später mit dem Echten Server passiert fast das Gleiche, einfach über das Internet.
Auf geht’s zum Admin
Wir erinnern uns, dass in der urls.py die url admin/ definiert war. Mal schaue, was es da zu sehen gibt:
no such table: django_session
Darf ich vorstellen: Die Debug-Seite von Django. Das Sieht im Moment nach viel Text aus, aber du wirst später dankbar für jede Information sein, die dir hier angezeigt wird.
In den meisten Fällen willst du an dieser Stelle diesen geheimen Trick anwenden: Du suchst den Fehler in einer Suchmaschine deiner Wahl und klickst auf den ersten Link (nach den Werbungen), der dich normalerweise auf Stack Overflow führt.
In diesem Fall verrate ich dir, woran es liegt: Wir haben noch keine Datenbank erzeugt, deshalb fehlt auch die Tabelle, die Django hier sucht.
Datenbank erzeugen
Migrate
Die 18 unapplied migrations, die wir vorhin gekonnt ignoriert haben, holen uns nun wieder ein.
Der Zusammenhang zwischen migrations und Datenbanken wird später noch erläutert, wenn wir unsere eigene Django-App machen. Für den Moment musst du nur wissen, dass mit diesem Befehl deine Datenbankstruktur erzeugt wird.
python manage.py migrate
Die Meldungen sollten anzeigen, dass alles geklappt hat und wir sollten nun eine db.sqlite3 neben unserer manage.py finden:

Das ist unsere Datenbank, komplett in einer Datei. Wie gesagt: Zum Testen reicht das.
Probieren wir es nochmal mit dem Admin:
Nun solltest du auf eine Login-Seite gelangen.
Login & Django Admin
Auth
Tatsächlich haben wir noch keine Login-Daten. Aber natürlich gibt es auch dafür einen Befehl im manage.py.
python manage.py createsuperuser
Wenn du geforderten Eingaben machst und, wie ich, ein schwaches Password wählst, springt dir jetzt das AUTH_PASSWORD_VALIDATORS Setting ins Auge, das wir vorher einfach ignoriert haben. Es prüft ob dein Passwort die definierten Kriterien erfüllt. Du kannst aber auch hier sagen, dass es dir egal ist.
Login
Nun kannst du dich mit den Eben eingegebenen Zugangsdaten einloggen und gelangst zum Django-Admin. Die Sprache sollte deinem LANGUAGE_CODE-Setting Entsprechen.

Wenn du auf „Benutzer“ klickst siehst du sogar schon deinen ersten eigenen Eintrag in der Datenbank.
Die „Django-Verwaltung“, wie sie auf deutsch heisst, ist eine der Stärken von Django. Es ist eine Django-App (was sonst?), die es dir erlaubt mit wenig Programmieraufwand in die Datenbank zu schauen und Änderungen zu machen, ohne dich mit Datenbanken auseinandersetzen zu müssen.
Eine neue Seite erstellen
App
Wie Eingangs schon erwähnt, ist ein Django-Projekt aus Django-Apps zusammengebaut. Nun machen wir eine eigene App, um zu sehen, woraus diese besteht.
Wie beim Projekt, können wir mit einem einfachen Befehl eine leere Hülle für unsere app erzeugen. Ich nenne meine App myapp. Vielleicht bist du ja kreativer.
python manage.py startapp myapp
Juhe: Ein neuer Ordner myapp ist aufgetaucht. Schauen wir mal rein.
Viele Dateien, wenig Inhalt: Scheint als kämen wir nun endlich doch noch zum Programmieren.
Settings.py (wieder mal)
Aber bevor wir damit starten, wollen wir unsere App schon einmal aktivieren, sonst vergessen wir das nachher. Füge deine App in den INSTALLED_APPS hinzu. Ob am Anfang oder am Ende der Liste diskutieren wir ein andermal. Noch kommt es nicht darauf an.
INSTALLED_APPS = [
'myapp,
...
views.py
Theoretisch könnten wir unsere Logik in irgendeine eigene python-Datei packen. Typischerweise heisst diese Datei aber views.py, welche auch schon in unserer leeren App erzeugt wurde.
Hier fügen wir diese minimalistische Funktion ein.
from django.http import HttpResponse
def myview(request):
return HttpResponse('Hallo')
Es nimmt als Argument einen request, also das, was der Client dem Server senden. Zurück gibt es eine HttpResponse, die vom Server zurück an den Client geschickt wird. Soweit so gut. Jetzt müssen wir diese Funktion aber Zugänglich machen.
Noch eine urls.py
Interessanterweise enthält unsere leere App noch keine leere urls.py. Aber genau diese wollen wir jetzt erstellen mit folgendem Inhalt.
Aufgepasst: Das ist eine neue urls.py in deiner App, nicht jene vom Projekt.
from django.urls import path
from . import views
urlpatterns = [
path("", views.myview, name="index"),
]
Hier importieren wir unsere views.py und machen die myview Funktion zugänglich über einen leeren Pfad („“). Wir geben dieser „Route“ auch einen Namen und nennen sie liebevoll „index“. Mehr dazu ein Andermal.
Es ist nochmal Konzentration gefordert: Nun gehen wir wieder zurück zur urls.py vom Projekt.
Hier fügen wir folgenden Pfad hinzu.
path("my/", include("myapp.urls")),
Genauer holen (includen) wir hier alle Pfade aus der anderen urls.py. Das "my/" das wir hier als Pfad angeben, wird allen inkludierten Pfaden vorangesetzt. Damit können wir sicherstellen, dass die Pfade aus verschiedenen Apps sich nicht unabsichtlich überschatten. Denn falls der gleiche Pfad mehrfach definiert ist, wird der erste passende genommen.
Jetzt sollten wir unsere erste eigene Seite in Django sehen können:
Wenn deine Webseite dir nun „Hallo“ sagt, darfst du dir jetzt auf die Schultern klopfen. Andernfalls ist das deine Gelegenheit, dich mit der Debug-Seite anzufreunden. Oft, aber nicht immer, geben die Fehlermeldungen einen guten Hinweis darauf, wo etwas schief gelaufen ist.
models.py
Springen wir gleich zur Datenbank, oder dem was Django uns davon zumuten will. Wie zuvor erwähnt, „versteckt“ Django die Datenbank hinter einem sogenannten Object-Relational Mapping (ORM). Sehen wir uns an was das heisst.
In der models.py erstellen wir folgende Klasse.
class MyModel(models.Model):
name = models.CharField(null=True, blank=True)
Statt dem unkreativen MyModel könnten wir auch ein Velo, ein Kochrezept oder irgendetwas anderes definieren, das wir beschreiben und in der Datenbank speichern möchten. Wichtig zu verstehen ist, dass wir hier nur ein Modell definieren ohne den effektiven Inhalt. Wir beschreiben also z.B. nur, dass ein Kochrezept aus Zutaten mit Mengenangaben und Instruktionen besteht, ohne hier festzulegen, welches denn die Zutaten sind. Das machen wir später, wenn wir Kochrezepte „erstellen“.
Zurück zu meinem unkreativen Beispiel: MyModel ist ein Ding, das einen Namen hat. Darum gebe ich dem Modell ein Feld, wo ich diesen Namen ablegen kann.
Mit dem null=True und blank=True sage ich dem Modell, dass der Name nicht erforderlich ist. Das Feld darf also leer bleiben, wie wir später feststellen werden.
admin.py
Wie vorgängig erwähnt, ist es ziemlich einfach eine Admin-Seite für unser Modell zu erstellen.
Die admin.py in deiner App, wird später vom Django-Admin automatisch durchsucht. Hier können wir, wie in der Datei mit „Register your models here“ angepriesen, angeben, dass MyModel auch eine Seite für die Administration bekommen soll:
from .models import MyModel
admin.site.register(MyModel)
Später können wir die Admin-Seite unseres Modells noch viel weiter ausschmücken und eigene Funktionen hinzufügen. Vorerst belassen wir es bei diesem Minimalistischen Beispiel.
Wenn du nun wieder den Admin öffnest, findest du einen neuen Eintrag für dein Modell.
Beim versuch diesen zu öffnen, werden wir aufgehalten mit:
no such table: myapp_mymodel
Datenbank anpassen
Wenn wir ein Modell erstellen oder eines ändern, bedeutet das jeweils auch, dass die Datenbank angepasst werden muss. Glücklicherweise unterstützt uns Django hier.
Stellen wir uns vor, wir hätten unsere App bereits veröffentlicht und diverse Webseiten weltweit verwenden sie bereits aktiv. Wenn wir nun eine Änderung am Modell machen, müssen wir all diesen Leuten irgendwie sagen, dass sie ihre Datenbank anpassen müssen, sobald sie unsere neue Version der App installieren. Dies machen wir, indem wir eine Migrations-Datei erstellen, oder besser gesagt von Django erstellen lassen:
python manage.py makemigrations
Wenn du obigen Befehl ausführst, wird eine neue Datei im Ordner migrations erzeugt. Darin stehen alle Änderungen, die an Modellen gemacht wurden. Django vergleicht dazu den Inhalt aller bestehenden Migrations-Dateien mit den Modellen, wie du sie derzeit in models.py definiert hast. Dies tut es soweit es geht automatisch. Falls wir komplexere Migrationen benötigen, können wir auch händisch Migrations-Dateien anpassen. Für den Moment brauchen wir das nicht.
Die Migrations-Datei wird mit dem Projekt veröffentlicht, so dass alle, welche die App benutzen, bei sich die Migration ausführen können. Wie das geht haben wir bereits gelernt:
python manage.py migrate
Nun kannst du dein Modell im Admin öffnen und Objekte dieses Modells erstellen.

Probiere es aus.
Objekte und Templates
Nun wissen wir, wie wir Informationen in die Datenbank ablegen können. Nun wollen wir diese aber auch anzeigen.
Dazu müssen wir in unserem myview im views.py zuerst die entsprechende Information aus der Datenbank holen.
Mit MyModel.objects erhalten wir zugriff auf die Objekte unsere Modells. Wir können damit nach bestimmten Objekten filtern und vieles mehr. Für diese Einführung halten wir es simpel und laden einfach das erste Objekt unseres Modells:
from .models import MyModel
def myview(request):
my_model_object = MyModel.objects.all()[0]
...
Nun wollen wir den Namen diesen Objekts anzeigen. Wir können wie zuvor diesen einfach im HttpResponse zurückgeben. Später wollen wir aber ganze HTML-Seiten erzeugen und zurückgeben. Um die Erzeugung dieser HTML-Seiten zu vereinfachen, bringt Django eine Template-Sprache mit.
Ein Template ist nichts anderes als ein HTML-Dokument mit ein paar Platzhaltern und Anweisungen. Hier ein simples Beispiel, das wir nachher verwenden werden. Erzeuge in deiner App einen Ordner templates und darin einen Ordner myapp (oder wie deine App heisst) und darin eine Datei index.html.

Schreibe darin folgendes:
<p>{{ my_model_object.name }}</p>
Die umgebenden <p> definieren einen Paragraph in HTML. Die geschwungenen Klammern hingegen, sind Platzhalter für das Django-Template. Hier greifen wir auf den Namen unseres Objekts zu und lassen ihn an dieser Stelle abdrucken.
Zurück in der view.py müssen wir nun das Template laden und die Kontextinformationen übergeben. So sieht das aus, wenn wir es komplett ausschreiben würden:
from django.template import loader
def myview(request):
my_model_object = MyModel.objects.all()[0]
template = loader.get_template("myapp/index.html")
context = {
"my_model_object": my_model_object,
}
return HttpResponse(template.render(context, request))
Wir laden das Template, das wir zuvor erstellt haben, erzeugen ein dictionary für unsere Kontextinformationen und übergeben das gerenderte (also ausgewertete) Template als Antwort zurück.
Um diese Schritte ein Wenig zu vereinfachen, bietet Django eine Abkürzung an, die das Gleiche tut:
from django.shortcuts import render
def myview(request):
my_model_object = MyModel.objects.all()[0]
context = {
"my_model_object": my_model_object,
}
return render(request, "myapp/index.html", context)
Wenn du nun nochmal deine erste Seite öffnest, siehst du, dass der Name deines ersten erzeugten Objekts, anstelle von „Hallo“ auf dem Bildschirm erscheint.
Falls du noch kein Objekt erstellt hast, reklamiert Django. Hole das in dem Fall im Admin nach.
Nächste Schritte
Wir haben gelernt, wie Django aufgebaut ist, wie wir ein Projekt mit einem einfachen Modell von Grund auf erstellen und wie wir die Entwicklungsumgebung und eine Testdatenbank aufsetzen.
Von hier aus gibt es noch sehr vieles zu entdecken. Falls du nicht bis zum nächsten Kurs abwarten möchtest, kannst du wie folgt schon weiterentdecken.
Lade Juntagrico herunter
Hole dir den Code von Juntagrico. Du wirst darin die Grundstruktur wiedererkennen, aber auch vieles mehr entdecken.
In PyCharm kannst du dein Projekt via File > Close Project schliessen und danach oben rechts Get from VCS anklicken.

Gib dann folgende URL ein https://github.com/juntagrico/juntagrico.git und klicke anschliessend auf Clone.
Lass dir von PyCharm eine venv erstellen und erzeuge dann eine Test-Datenbank und starte den lokalen Server, wie zuvor beim eigenen Projekt:
python manage.py migrate
python manage.py runserver
Django Dokumentation
Django ist ein hervorragend dokumentiertes Projekt. Hier findest du auch viele hilfreiche Tutorials.
https://docs.djangoproject.com/en/4.2/