Apps sollen reusable sein → Projekt in logische Einheiten teilen
Anlegen neuer App
docker-compose run django python manage.py startapp my_first_app
Anschließend in INSTALLED_APPS innerhalb der "settings.py" eintragen
Der erste View
Der erste View
„Views sind Python-Methoden, die einen Request entgegen nehmen und mit einem Response antworten“
Zitat: Die Tutoren (heute)
Der erste View
werden über eine/mehrere Path(s) angesprochen
Dispatcher weiß dadurch ob/was er tun muss
Pflege der Zuordnungen in "urls.py"
Beispiel
Und jetzt dein
erster View!
Hier gehts zur Aufgabe
Erstelle in deinem Projekt eine neue App "first_app"
Lege in dieser neuen App einen View an, der eine Zahl anzeigt und einen Link anbietet, um die
Zahl um 1 zu erhöhen, sowie einen weiteren Link um die Zahl um 1 zu verringern
Lege einen weiteren View an, der den Benutzer nach einem Namen fragt
Der Name soll abgesendet werden können und anschließend den Benutzer mit seinem Namen
freundlich
begrüßen. Außerdem soll die Begrüßungsseite einen Link zurück zur Namenseingabe enthalten.
Dein Formular im HTML setzt normalerweise ein POST-Request ab. Die Daten daraus kannst
du aus dem
request-Parameter
deines Views auslesen.
🎉 Fertig 🎉
Wenn du noch Zeit hast, versuche doch auf eine Falscheingabe (leer?) des Namens in Aufgabe 3 mit
einer entsprechenden Meldung zu reagieren.
Lege in deiner „first_app“ ein neues Verzeichnis „templates“ an.
Platziere
dort eine neue „first_template.html“ (Rechtsklick auf den Ordner -> „New“
->
„HTML File“) und fülle den Body mit etwas Text. Lege einen neuen View sowie Route
an,
der die neue „first_template.html“ über den „render()“-Shortcut
(Django-Render-Shortcut)
ausgibt.
Deine Laufzeitumgebung enthält schon eine Fremd-App namens „bootstrap4“ die das
Bootstrap-CSS-Framework bereitstellt.
Die Library bietet verschiedene Template-Tags an, die eine
Einbindung der Static-Files von Bootstrap erleichtern.
Binde die App „bootstrap4“ in dein Projekt ein („settings.py“). Lege ein
neues Template „first_bootstrap_template.html“ an und binde die CSS und JS Teile im
Head
des Dokumentes ein
(Django-Bootstrap4-Doku).
Teste alles mithilfe eines neuen Views, Route + einigen Features des Bootstrap Frameworks (z.B.
Alerts etc.).
Diese Zeilen
müssen in den <head> deines HTML-Dokumentes. Anschließend kannst du Bootstrap
vollumfänglich in deinem Template nutzen!
Kopiere das Template aus 2. als „base.html“. Dieses soll als Basis für beliebige
Seiten
verwendet werden können. Hier enthalten sein sollen alle Teile, die nicht spezifisch einer
bestimmten Seite zugeordnet werden können (Header, Imports, evtl. Basislayout der Anwendung).
Ersetze alle Stellen, die Inhalt enthalten, durch Blöcke, die durch spätere Templates dann mit
Inhalten gefüllt werden können (DTL-Doku).
Erstelle ein weiteres Template, das die gleiche Seite erzeugt wie 2., aber
selbst
nur das „base.html“
extended und die notwendigen Blöcke befüllt. Zeige die Seite über einen eigenen View + Route an.
Lege ein Template an, das vom View per Kontext eine Liste von (deinen Lieblings-😄) Serientitel
erhält und diese in einer zweispaltigen Bootstrap Tabelle anzeigt. Titel, die ein Leerzeichen
enthalten, sollen dabei mit dem Info-Background (Blau) hinterlegt werden. Die Nummer des Titels
kannst du vom View aus mitgeben - musst du aber nicht. Versuche es auch mal ohne 😄
„You have been rickrolled!“ 😜 Dafür jetzt ein wirklich
sinnvoller Hinweis: Jinja2 ist eine weitere Templating-Sprache die offiziell von Django unterstützt
wird. Werf doch mal einen Blick in
deren Doku!
Datenhaltung
aka. „Models“
Wie funktioniert Datenhaltung in Django?
Integrierter ORM
Tatsächliche DB für den Entwickler i.d.R. transparent
„Models“ = Klassen, die alle persistenten Daten enthalten
(in „models.py“)
Automatisch generierte Migrationen für Model-Änderungen
Lege eine neue App „gallery“ an. Diese App werden wir im Laufe dieses Praktikums
immer weiter zu einer vollwertigen Fotogalerie weiterentwickeln.
Lege in der App „gallery“ ein Model (soll ein Foto repräsentieren) mit folgenden
Attributen (passender Datentyp!) an: file (benötigt), title (optional), capture_date (optional)
Lasse von Django entsprechende Migrationen erstellen und migriere deine Datenbank.
Damit Django weiß, wo vom Benutzer hochgeladene Dateien etc. gespeichert werden sollen, muss man
zwei Parameter in settings.py setzen:
MEDIA_ROOT: Absoluter Pfad zu einem Ordner, in dem die Dateien
gespeichert werden sollen
(z.B. „os.path.join(BASE_DIR, 'media_root/')“)
MEDIA_URL: URL unter der die hochgeladenen Daten angeboten werden (z.B.
„/media/“)
MEDIA_ROOT und MEDIA_URL sind nicht ganz trivial zu verstehen. Im Endeffekt zeigt
MEDIA_ROOT auf einen tatsächlichen Ordner deines Dateisystems in den Django dann
alle Dateien packen kann, die irgendwohin müssen. Die MEDIA_URL wird automatisch
vor alle URLs gepackt, die auf Dateien in genau diesem Ordner zeigen sollen -
hierdurch ist z.B. auch möglich das Bereitstellen der Dateien auf einem völlig anderen
Server zu realisieren. Vielleicht schießt dir da ja gleich ein S3-Bucket durch den
Kopf 😄?
Letztendlich müssen die Dateien auch tatsächlich von irgendeinem Server über eine URL angeboten
werden (in Production übernimmt das z.B. nginx oder Apache) - für unsere Entwicklungsumgebung
können wir da den Development-Server bemühen. Folge hierfür der offiziellen Anleitung.
Lege zu allen Beispielfotos im Ordner „example_data/photos“ Instanzen über die interaktive Konsole an und fülle sie mit entsprechenden
Daten (hilfreiche
Doku).
Denke daran, dass du eine der mächtigsten Skript-Sprachen zur Hand hast. Vielleicht kann sie dir Arbeit abnehmen? 😄
Python kann dir alle Dateien eines Verzeichnisses ausgeben
(os.listdir()).
Darüber zu iterieren bekommst du selbst hin 👍
Erstelle einen neuen View („Galerieansicht“), der alle aktuell vorhandenen Fotos aus
der Datenbank läd und in einer Kachelansicht anzeigt. Denke an ein sinnvolles Basis-Template von
dem deine restlichen Templates ableiten. Einzelne Apps können auch selbst URLs definieren, die
dann
vom Gesamtprojekt eingebunden werden können (auch z.B. unter einem Präfix-Pfad) - das kann in
vielen Fällen sinnvoll sein, um die „urls.py“ übersichtlich zu halten. Lege eine
eigene
„urls.py“ für deine „gallery“-App an und pflege die URLs, welche die
Fotogalerie betreffen
zukünftig dort (wie?).
Es ist schwer zu empfehlen zumindest einmal die Doku zu jedem Template-Tag/-Filter zu lesen (am
einfachsten, wenn du ihn das erste mal verwendest):
Template-Tag-Doku
🎉 Fertig 🎉
Wenn du noch Zeit hast, stöbere doch mal in folgender Homepage: Django-Packages
Sie enthält eine gigantische Sammlung an fertigen Libraries/Tools für deine Arbeit mit
Django. Fast alles hat jemand schon mal gelöst - don't reinvent the wheel!
Datenbank-Migrationen
🎉 Nie wieder SQL 🎉
Django-Database-Migrations
existieren pro App
überführen von einem Datenbankstand in einen neuen
vollständig datenbank-unabhängig
Python-Source-Code
Teil des Projektes → einchecken!
ausgeliefert? → nie wieder verändern!
= App kann aus jedem Entwicklungsstand heraus auf die neueste Version gehoben
werden
manage.py makemigrations
erstellt in 95% der Fälle Migrationen automatisch/interaktiv
restliche Fälle: Datenmigrationen
werden auch als Python-Source-Code geschrieben und funktionieren über dieselben
Mechanismen
Lass Django
die Migrationen machen!
Hier gehts zur Aufgabe
Füge ein weiteres optionales Attribut „comment“ zum Foto-Model hinzu, in dem ein
längerer Freitext-Kommentar zum Bild gespeichert werden kann.
Die Galerieansicht ist aktuell nicht sehr performant, da alle Bilder in voller Auflösung an den
Client übertragen werden müssen, obwohl wir eigentlich nur eine kleine Version des Bildes
anzeigen. In deiner Entwicklungsumgebung ist schon eine Django-App
„sorl.thumbnail“
enthalten, die hier Abhilfe schaffen kann. Verwende das dort mitgelieferte „ImageField“
in deinem Foto-Model und passe deine Templates entsprechend an.
Bonusaufgabe
Füge zwei neue required und nicht editierbare Attribute „width“ und „height“
hinzu, die entsprechend die Höhe + Breite des Fotos enthalten. Bestehende Instanzen müssen
hierzu den Wert über eine Datenmigration erhalten. Bewährt hat sich hier folgendes Vorgehen:
Dein Projekt enthält schon Pillow
- eine Library um in Python mit Rastergrafiken umzugehen. Das ImageField hat ein
Attribut "file", das du mit Pillow öffnen kannst um an die Informationen des Bildes
(wie z.B. die Größe) zu kommen.
🎉 Fertig 🎉
Noch Zeit übrig?
Lies dich doch etwas in die Django Debug
Toolbar
ein - ein wirklich cooles Tool um deine Views etc. übersichtlich zu debuggen!
Forms
Was sind Django-Forms?
Beispiel
Model-Forms
Automatische Erstellung einer Form aus einem Model
Erzeugter HTML-Code
Jetzt deine
eigenen Forms
Hier gehts zur Aufgabe
Erstelle ein neues Model „Person“ in deiner „first_app“ mit folgenden
Attributen:
first_name (required, String)
last_name (required, String)
birthday (required, Date)
favourite_beverage (required, Einfachauswahl)
Geburtstage dürfen nicht in der Zukunft liegen (siehe hier)
friends (optional, M2M zu Person)
Der Vorname darf im Falle eines Nachnamens „Mustermann“ nicht „Max“
lauten (siehe hierzu .clean() )
Erstelle einen View + Template um eine Person über ein ModelForm anzulegen.
Validierungsfehler sollen angezeigt werden.
Erstelle einen View + Template um eine Person über ein ModelForm zu editieren.
Validierungsfehler sollen angezeigt werden.
Bonusaufgabe
So richtig toll sehen die Forms aktuell vermutlich nicht aus - natürlich hast du die Möglichkeit
das Formular von Hand über Bootstrap-Klassen zu stylen. Das bedeutet jedoch auch, dass du deine
Templates bei jeder Änderung an den Models anfassen musst. Django has you covered!
Dein Projekt enthält eine Django-App namens crispy-forms.
Ändere deine Forms/Views/Templates so ab, dass crispy-forms das Rendering deiner Formulare
übernimmt (insbesondere über den „crispy“-Template-Tag; nicht den „crispy“-Filter).
Vergiss dabei nicht das CRISPY_TEMPLATE_PACK in deiner settings.py richtig zu setzen.
Bonusaufgabe
Erstelle eine Ansicht, die tabellarisch alle Personen anzeigt, die aktuell in der Datenbank
vorhanden sind. In der letzten Spalte soll ein Link zum Bearbeiten der Person vorhanden
sein. Ergänze deine Ansicht der Benutzertabelle außerdem um ein Formular, um nach Benutzern mit
einem bestimmten Lieblingsgetränk zu filtern.
🎉 Fertig 🎉
Noch nicht genug?
Django-Crispy-Forms ist sehr mächtig und trotzdem voll anpassbar - lies dich doch etwas in
die Doku zur Erstellung eigener
Template-Packs ein.
(Generic) Class-Based-Views
Was sind Class-Based-Views?
Klassen, die eine dispatch()-Methode anbieten
dispatch() wird vom URL-Dispatcher aufgerufen (wie eine View-Methode)
Modular + erweiterbar durch Vererbung etc.
Beispiel
Und was sind Generic Views?
Mitgelieferte Views, die alle Standardfälle abdecken
Immer Konglomerat aus Mixins + Basis-View
Mixins implementieren Funktionalität
Werden im Basis-View nur noch aufgerufen + zusammengesteckt
Empfehlung: Immer zuerst in Django-Doku nachsehen, ob es schon was Fertiges gibt
Beispiel BaseDetailView
Langsam wird's
richtig produktiv
Hier gehts zur Aufgabe
Baue deine Views zum Anlegen/Editieren von Person-Objekten auf Class-Based-Views um. Verwende
hierzu die Generic-Views, die Django schon mitliefert. Interessant ist auch das Handling
bei einem erfolgreichen Speichern (also keine ValidationErrors), denn hierbei muss Django
entscheiden, wohin der Anwender weitergeleitet wird. Django gibt dir bei fehlender Konfiguration
Hinweise, was du tun musst!
Im Standardfall verwendet Django die
get_absolute_url()-Methode
deines Models und leitet nach dem Speichern auf die dort zurückgegebene URL weiter.
Ergänze in deiner „gallery“ App neue Views zum Anlegen, Bearbeiten und der
Detailansicht von Fotos über CBVs. Im Anlegen- und Bearbeiten-Fall sollen alle Attribute
angezeigt werden. In der Detailansicht soll das Foto recht groß inklusive des Titels angezeigt
werden.
Bonusaufgabe
Man soll einzelne Bilder auch löschen können - implementiere hierzu die Funktionalität inkl.
einer Rückfrage, ob man sich wirklich sicher ist.
Die Dokumentation des
DeleteView
könnte dir helfen!
Bonusaufgabe
Aktuell lassen wir den Benutzer im Dunklen, ob das Anlegen/Bearbeiten/Löschen überhaupt
funktioniert hat - das wollen wir ändern. Django bietet über das Messages-Framework
eine integrierte Möglichkeit einmalige Benachrichtigungen an den Benutzer weiterzugeben, die
über genau solche Sachverhalte aufklären. Implementiere entsprechende Messages beim
Anlegen/Bearbeiten/Speichern. Das Basis-Template ist ein guter Platz diese Messages zu rendern.
Beachte auch die Dokumentation von django-bootstrap4 in Bezug auf messages.
🎉 Fertig 🎉
Noch Zeit übrig?Kennst du noch Timsort?
Entwickelt wurde der Algorithmus von Tim
Peters - der zufälligerweise auch sehr aktiv an Python mitgewirkt hat. Ihm ist ein
Easter-Egg in Python gewidmet. Öffne eine Python-Console und gib „import this“ ein.
Sich an die Regeln zu halten ist der erste Schritt zu hervorragendem Python-Code 🐍
Django-Admin
Was bietet Django-Admin?
Mitgelieferte Django-App „django.contrib.admin“
Erzeugt automatisch Ansichten um Model-Instanzen zu erstellen/bearbeiten/löschen
Lege einen neuen Superuser (alle Berechtigungen) über „manage.py“ in deinem Projekt
an (wie??).
Logge dich in die Admin-Ansicht deiner Anwendung ein („/admin“). Aktuell kannst du
nur zwei Models
verwalten: User und Group. Deine selbst angelegten Models sind noch nicht für die Verwendung mit
Django-Admin konfiguriert. Hole dies in den „admin.py“-Dateien deiner Anwendung nach
(pro App).
Lege ein neues Foto über die Admin-Ansicht an und beobachte, wie es in der Gallerieansicht
auftaucht sowie über deine selbst erstellten Views bearbeitet/gelöscht werden kann. In der
Admin-Ansicht gibt es sogar einen Button „View on site“, der durch die Definition
deiner absolute_url am Model ermöglicht wird.
Lege über die Admin-Ansicht einen neuen Benutzer an, der kein „Staff“-Benutzer ist.
Versuche dich mit diesem an der Admin-Seite anzumelden.
Gib dem Benutzer nun „Staff“ aber nicht „Superuser“. Melde dich erneut
an. Was fällt dir auf?
Du kannst feingranular steuern, was ein Benutzer/Gruppe darf - gibt dem Benutzer ausreichende
Rechte, um Fotos anzulegen - sonst nichts. Wie sieht die Admin-Ansicht nun aus?
Lege eine Gruppe „Photo-Admin“ an, die allumfassend Fotos administrieren darf. Gibt
diese Gruppe deinem neu angelegten Benutzer. Wie sieht die Ansicht für diesen Benutzer nun aus?
🎉 Fertig 🎉
Noch Zeit übrig? Du kennst jetzt eigentlich alle Grundbausteine von Django - was würdest du
sagen, dass die Grenzen von Django sind? Wann glänzt es? Schreib deine Gedanken auf - wir werden sie
nachfolgend diskutieren!
Django-REST-Framework
Django-REST-Framework
Dritt-Django-App
Erzeugt vollautomatisch eine CRUD-REST-API zu Models
Sogar Views zum Erforschen im Browser
Perfekt um Django als Backend für JS/Mobile-App zu verwenden
Beispiel: Photo Model
Ergebnis
🎉 Geschafft! 🎉
Vielen Dank für deine Teilnahme
Du hast immer noch nicht genug? Schon mal was von Phoenix-LiveView gehört? Sowas
ähnliches gibt's für Django auch: Django Sockpuppet. Kombiniere das
noch mit Alpine.js und du hast Anwendungen, die sich
anfühlen wie React/Vue.js aber nur mit ⅓ der Arbeit. Das glaubst du nicht? Probier es doch aus - das
Rüstzeug hast du jetzt! 😄