 Hallo, wir reden heute über Django. Der Talk richtet sich vor allem an Leute, die aus manchen oder anderen Gründen Django-Projekte irgendwo in Produktion laufen haben. Das heißt, ich gehe erst mal davon aus, dass ihr jetzt oder irgendwann in Zukunft als Admins mit diesem ganzen Python Django-Geraffel interagieren müsst. Wenn ihr aber selber damit entwickelt oder auch nur Interesse daran habt, das ist auch für euch, denn es kommt ein oder zwei oder vielleicht auch noch ein paar mal öfter der Satz vor, das müsstet ihr dann den Entwicklern denn sagen, sagt euren Entwicklerinnen, sie sollen darauf achten, das könnt ihr dann zurückgehen lassen und so weiter. Das heißt, wenn ihr selber damit entwickelt, könnt ihr quasi diesen Arbeitsschritt verhindern in Zukunft. Das ist, denke ich, ganz gut. Die Folien werden natürlich online sein, also, ihr müsst nicht euch Dinge merken oder mitschreiben oder so alberne Sachen. Ich bin Rix. Ich entwickle mit Django. Ich habe damit ein Haufen Erfahrung. Ich habe kleine, große, mittlere Django-Projekte geschrieben und in Produktionen laufen und auch anderer Leute Django-Projekte in Produktion laufen. Das heißt, ich kenne den Frust der Interaktion da sehr gut. Also, ich habe an Predix mitgearbeitet, Pre-Talks geschrieben, aber auch ein Haufen kleinerer Sachen. Ja, dieses Django, Django ist ein Web-Framework. Das wisst ihr vermutlich, wenn ihr hier drin sitzt. Das ist in Python geschrieben. Es ist das älteste oder eins der ältesten Python-Web-Frameworks. Das ist über zehn Jahre alt und mittlerweile auch sehr stabil und abgehangen. Es gibt also mittlerweile eine vernünftige Release-Policy und ein Release-Prozess und sogar einen Ablauf. Das sieht man ganz gut. Es gibt LTS-Releases. Die sind auch gleich drei Jahre am Stück supportet und die kriegen die ganzen Updates und Security Fixes. Es ist mittlerweile einfach sehr, sehr gut durchdacht. Das Ganze wird von der Django Software Foundation im Hintergrund managed. Die bekommt Geld von diversen Geldgebern, wer halt so ein Open Source-Projekt gerade Geld gibt und lenkt das Geld dann um in Django-Konferenzen, aber vor allem auch an immer so ein bis drei Leute, die gerade von der DSF Geld bekommen, um sich dafür um gerade so den Release-Prozess zu kümmern, die Security-Releases machen, die aber vor allem auch dieses ganze Open Source-Geraffel auf GitHub managen, also pull requests reviewen, pull requests merging, Issues als Release-Blocker klassifizieren und dann fixen und so. Das sorgt dafür, dass Django mittlerweile sehr angenehm geregelten Life-Zeichen hat und man damit sehr gut interagieren kann. Ansonsten funktioniert Django wie mittlerweile die meisten Web-Frameworks. Das bietet den Entwicklenden, die in Python arbeiten, die Möglichkeit von irgendwo Request reinzubekommen, auf den Dinge zu machen, mit einer Datenbank vernünftig zu interagieren, sodass man da irgendwie sich nicht mehr direkt persönlich um SQL Gedanken machen muss, sondern möglichst viel hinter Python verstecken kann. Das, wie das so ist, seine Vor- und Nachteile hat. Und auch Interaktionen mit File Systems und sonstigen Dienstenden ein bisschen weggrappt. Und insgesamt versucht den Leuten das Leben so leicht wie möglich zu machen und so dokumentiert wie möglich zu machen und Entwicklerinnen davon abhält, gleich Experten für alles auf einmal sein zu müssen. Und das macht es insgesamt auch ganz gut. Interagieren tut man mit Django meistens über eine Datei, die heißt Manage.py und die liegt irgendwo. Wir kommen später auf das irgendwo noch zurück. Ihr müsst das hier auch nicht alles sehen und lesen können, dass das nur wiederes Output-Format so üblicherweise aussieht. Das ist jetzt Manage.py Help, also man ruft diese Datei auf und gibt dann halt wieder so übliche Befehle mit und Flex mit. Das ist alles sehr normal und gewohnt, ist auch alles dokumentiert. Und gerade mit diesem Help-Befilg kann man sich da auch interaktiv ganz gut weiterhangeln, wenn man nicht weiß, was man machen will. Das hatten ein paar Befehle, die ihr können kennen sollte. Das gibt ein paar Befehle, die nur die Entwicklerinnen benutzen sollten. Es ist nicht wirklich markiert, welches welche sind. Deshalb reden wir dann nachher mal drüber. Ansonsten unterstützt Django in Handvoll Datenbanken einfach out of the box. Hoffentlich sind das die, die ihr braucht. Das ist Harich. Es unterstützt natürlich Postgres. Ich werde hier so ein bisschen davon ausgehen, dass ihr, wenn ihr es könnt, Postgres benutzen werdet. Es unterstützt aber natürlich auch Maria db und MySQL. Es unterstützt daneben SQLite, was für kleine Projekte auch völlig akzeptabel ist. Aber sobald regelmäßig mehrere Menschen gleichzeitig auf eure Datenbank oder auf ihre Webseite zugreifen müssen, ist nicht mehr die beste Option. Aber vermutlich werden die Leute, die für euch dieses Projekt entwickelt haben, auf SQLite getestet haben. Das heißt, wenn es zu Problemen kommt, sollte man immer im Hinterkopf beiden, dass SQLite halt einen etwas anderen Funktionsumfang, als zum Beispiel ein Postgres hat und mögliche Probleme auch aus dieser Diskrepanz kommen könnten. Außerdem, und ich hoffe, das interessiert euch überhaupt nicht, unterstützt Django auch Oracle db. Und danach gibt es noch 3rd-Party-Libraries, die machen das Django auch mit noch schöneren Dingen, wie MSSQL umgehen kann. Auch da, ich hoffe ihr müsst damit nicht, macht dann auch weniger Spaß. Der Featureumfang ist auch kleiner. Ihr könnt jederzeit auf der Django-Webseite nachgucken, welche Version dieser Datenbanken gerade unterstützt sind. Wenn ich mich richtig erinnere, ist bei Postgres gerade 9.6. Und ihr solltet im Hinterkopf haben, dass bei Maria db und MySQL eine relativ niedrige Nummer als supported angegeben ist. Aber wenn ihr den vollen Featureumfang wollt, gerade so JSON-Felder, dann müsst ihr halt entsprechend höher ansetzen. Es kann unter aktuellem Debian manchmal ein bisschen hakelig werden. Right. Als Entwickler schreibt man, oder als Entwicklerin schreibt man sogenannte Modelle. Das ist ja auch für Web-Frameworks ziemlich typisch aktuell. Diese Modelle entsprechend ziemlich 1 zu 1 nach Datenbank-Tabelle. Man schreibt die einfach in Python vor sich hin, weil man so weit ist und denkt, das ist jetzt mein Modell, habe ich gut designed. Lässt man das von Django in eine sogenannte Migration überführen. Migration ist erstmal auch nur eine Python-Datei, die man dann später mit dem Befehl MyGrate in die Datenbank überführen lassen kann. Django geht dann hin, liest diesen Python-Pfeil und übersetzt das in das für die aktuelle Datenbank eben relevante SQL. Wäre natürlich schön, wenn es da nur eins gäbe, aber so ist das mit den Dialekten. Ihr werdet hoffentlich mit diesem ganzen Migrationsgeraffe einfach nur in Kontakt kommen, indem ihr einmal pro Update oder pro Installation MyGrate aufruft. Dann laufen Migrationen durch. Der Output sagt euch auch, aus welchem Umfeld die gerade kommen und dann ist alles schnuffig. Ihr könnt es auch 3-mal hintereinander ausrufen. Da kommt im Servicefeldern hier so ein NoMigrationsToApply-Output. Wenn ihr dann updated, dann könnt ihr euch auch mit ShowMigrations vorher angucken. Oh ja, jetzt kommen da noch 3 Migrationen dazu. Die sollten eigentlich safe sein, aber natürlich die führen Transformation auf eurer Datenbank aus. Also Backups vorher, super Idee. Backups hinterher, zu spät. Ihr könnt eigentlich alles, was dabei schiefgehen kann, hinterher noch fixen, aber es wird unangenehm. Also wenn ihr da in Konflikte lauft, wenn die entwickelnden Probleme gebaut haben, in zum Beispiel Datenmigration, die meisten Migrationen kann man eigentlich, sollte man alle Migrationen zurückrollen können, sobald aus der Entwicklung eigene Migrationen kommen, die was an Daten spielen, kann es sein, dass sie das vergessen haben zu implementieren. Das könnt ihr dann mit sehr viel Gusto zurückgehen lassen und mit ihr habt die Datenbank kaputt gemacht, rettet mal. Aber in aller Regel werdet ihr das nicht brauchen. Ist trotzdem relevant dazu zu wissen, dass man nicht nur, also wenn man Migrate sagt, dann versucht es auf den aktuellsten Stand zu kommen, man kann aber auch Migrate und dann den Namen des Verzeichnisses und den Namen der Migration angeben. Die liegen in einem Migrationsverzeichnis und dahinter haben die halt eine Zahl und einen Namen im Dateinamen. Wenn ihr das angebt, dann versucht Django auf genau den Stand dieser Migration zu kommen und zwar indem es entweder nach vorne oder nach hinten zurückmigriert. Dass zusammen mit Showmigrations sollte alle Situationen lösen können. In aller schlimmsten Notfall könnt ihr auch ändern, was Django über schon durchgeführte Migrationen weiß. Dafür gibt es den Switch Minus Minus Fake. Also ihr könnt quasi die Änderungen selber an der Datenbank durchführen und dann sagen, ja Django glaubt mir mal, ich hab das gemacht. Es glaubt es euch dann auch, aber das heißt natürlich, wenn ihr das nicht vollständig oder nicht richtig gemacht habt, dann knallt das auf sehr unangenehme und sehr schwer zu reparierende Weise. Und wenn das nicht funktioniert, kann man im schlimmsten Fall auch in die Datenbank gehen und da die Migrationstabelle, weil Django zieht diese Informationen, was schon migriert wurde und was nicht, aus einer Migrationstabelle, die in dieser Datenbank liegt. Was eine zirkuläre Abhängigkeit ist irgendwo, die relativ selten einem auf die Füße fällt. Spannenderweise. Also ihr könnt auch diese Tabelle von Hand bearbeiten, aber das empfiehlt sich fast nie, eigentlich nie quasi. Ihr könnt, um die Datenbank zu kommen, könnt ihr den Befehl db-shell benutzen. Wenn ihr manage.py db-shell ausführt, dann holt sich Django aus der Konfig, über die wir nachher noch reden, schon mal alle Zugangsdaten, den Host, das Passwort und lockt euch mit dem angemessenen Datenbank klein und ein. Dann müsst ihr das Graffeln nicht selber zusammen kratzen und ihr habt dann auch nicht irgendwie db-credentials in eurer Shell-History stehen und so. Das will man ja auch nicht immer. Aber so macht man das. Es gibt Änderungen an Modellen, die man nicht sofort in der Datenbank haben will, wenn man entwickelt. Und es gibt Änderungen an Modellen, die man einfach vergisst, in die Datenbank zu übernehmen. Django erkennt es natürlich. Es geht hin und guckt, das sind diesen Python-Dateien dasselbe wie in unserer Datenbank. Oh nein, ist es nicht. Dann blendet das so ein sehr roten und sehr eindrucksvollen Text ein. Der sagt, oh, da sind Änderungen, die sind noch nicht in einer Migration abgewildet. Dann ist es nicht so, dass sie eine Migration zu erstellen. Wenn ihr dabei seid, das nur auf einem Server zu deployen, dann macht das bitte nicht. Das ist ungefähr so hilfreich. Wie gibt es das? Oh, du willst pushen, das geht nicht. Auf dem Server ist schon eine neue Version. Nimm doch git push-f. Das ist das selbe Level von hilfreich. Technisch richtig. Aber nie das, was ihr wirklich wollt. Weil wenn ihr das macht, dann gibt es eine Migration. Es ist einfach sehr, sehr unangenehm und auch sehr konfliktbeladen. Einfach nicht, diesen roten Text ignorieren. Diese zwei Zeilen sind nicht für euch. Richtig. Das ist so die Datenbank-Seite. Wenn Django Dateien oder das Dateisystem anfasst, kennt es da zwei verschiedene Dinge. Es gibt einmal die Media-Files. Media-Files sind Sachen, die von Endnutzern hochgeladen werden. Üblich sind da keine Ahnung. Profilbilder, andere Bilder, was auch immer eure Domäne ist. PDFs, whatever, Dateien jedenfalls. Die werden von Django so gehandhabt, dass die halt auf Platte liegen. Also nicht komplett in der Datenbank. Macht keinen Spaß, spätestens bei den Backups. Sondern nur den Dateipfad in der Datenbank abspeichert. Es gibt dafür dann einen Pfad. Sehen wir später bei der Config. Ihr solltet halt sicherstellen, dass dieser Pfad irgendwie vom Prozess schreibbar ist. Üblicherweise sagt man erst mal, ja, ist das halt dieses Mediaverzeichnis. Und da drin liegen dann user-hochgeladene Dateien. Und ihr solltet dafür sorgen, dass euer Web-Server das halt ausliefern kann. Also ja, EngineX, Apache, oder was auch immer. Gerade in der Entwicklung sieht man das oft so. Also ich kenne das von mir. Ich füge hier einen Dateifeld ein und da können dann Leute Dinge hochladen und ja, ja, später wird das ausgeliefert. Eigentlich ist es natürlich die Aufgabe der Entwicklung da drauf zu achten, dass das gerade in Sachen Zugriffsberechtigung dann hinkommt. Aber wie gesagt, man vergisst das oft und die Administration ist dann quasi so die letzte Bastion der Vernunft, bevor irgendwer das nicht finden sollte, das in freier Wildbahn sieht. Das heißt, das wäre dann auch an euch zu fragen, soll das eigentlich? Also sind alle Dateien, die in diesem Media-Ding landen öffentlich wirklich zugänglich? Soll das so? Muss das so? Und wenn nicht, das ist die Lösung, die ihr dann auch aktiv schon vorschlagen könntet, dass alle Sachen, die nicht direkt zugänglich sein sollen, sollen halt in separates Unterverzeichnis gelegt werden. Ihr liefert das eben nicht mit aus und eure Entwicklungsabteilung ist dann dafür verantwortlich, das einmal durchs Jungle zu schleifen und die angemessene Autorisierung durchzuführen. Damit eben nicht so was passiert wie Rechnungen sind mediafalls, die werden ja generiert, die liegen da und wenn man zufällig den richtigen Vater redet, dann sieht man halt die Rechnung anderer Leute. How bad can it be? Daneben gibt es auch noch statische Dateien, das ist alles, was so aus der Entwicklung groß fällt, um im Frontend angezeigt zu werden, also wenn euer Server nur ein AP Server ist, wahrscheinlich nichts, aber man hat selten das Glück auf einem reinen AP Server zu arbeiten, weil sich dann doch so Feature-Wurst dran arbeitet und das heißt, das sind CSS-Dateien, JavaScript-Dateien, Bilder, alles Mögliche drum und drum. HTML-Dateien in der Regel nicht, weil die eher so als Templates verarbeitet werden und nochmal einmal komplett durch Jungle durchgeschleift werden und rausgrindert werden, aber halt diese ganzen statischen Dateien müssen ja auch irgendwie raus, die werdet ihr im Laufe der Installation und im Laufe jedes Upgrades einmal mit dem Befehl Collect-Static einsammeln lassen und in ein konfiguriertes Verzeichnis legen lassen. Das könnt ihr dann tatsächlich sehr unproblematisch über den Web-Server rausleiten und auch dickes Caching gegenwerfen und so, die kriegen Herrschers mit den Dateinamen und alles. So sieht es aus, es sagt euch dazu, in welches Verzeichnis das gelegt wird und das heißt, ihr könnt da auch nochmal sehen, was genau passiert. Es fragt euch auch nochmal, ob das komplett neu generiert werden soll oder nicht. Das lässt sich natürlich die Skripte auch abschalten mit minus minus no input, aber grundsätzlich ist das eine relativ hilfreiche Interaktion mit Jungle. Möglicherweise ist da noch eine zusätzliche Bibliothek eingebunden, die sehr, sehr üblich ist, die heißt Jungle Compressor, die sorgt dann dafür, dass so JavaScript zusammengefasst und minified wird und CSS auch. Wenn das ist, dann müsst ihr nach diesem Collect-Static noch einmal Compress laufen lassen und euch auch nicht weiter darum kümmern. Die einzige Ausnahme ist, dass möglicherweise die Entwicklung beschlossen hat, dass ihr euch nicht um Static-Falls kümmern sollt. Dort müssen sie euch natürlich sagen. Dafür gibt es auch eine Bibliothek, die heißt White Noise, die übernimmt dann das Ausliefern der Statischen Datein direkt aus Jungle raus. Das ist nicht so eine schlechte Idee, wie es erstmal klingt, also das ist technisch gesehen wahrscheinlich ein bisschen langsamer, aber nicht so, dass es irgendwann auffällt, bevor ihr nicht in ganz andere Probleme verlaufen seid. Da müsst ihr einfach Kontakt mit der Entwicklungsabteilung oder den Entwicklern oder so suchen und euch sagen lassen, ob die Statischen Datein eh schon rauskommen oder nicht. Im Allgemeinen, wenn nicht irgendwie unübliche Sachen geändert werden, liegen die Statischen Datein dann im URL-Fahrt unter Slash-Static, also Slash-Static könnt ihr weggeschen und die Mediadatein unter Slash-Media. Die Installation von so einem Projekt, da müssen wir darüber reden, wie man installiert und es ist leider immer so ein bisschen hakelig. Es gibt da einen Haufen verschiedener Ansätze und vor allem auch ein Haufen verschiedener Umgebungen, die man nutzen kann. Wenn man pip, was der Python-Paket-Manager ist, einfach so ausführt, dann installiert der Dinge in euer globales Betriebssystem-Kontext, was auch immer einfach rein, also die Bibliotheken sind dann für das System Python zugänglich und wenn Binarys mitkommen, dann sind die auch für alle und das will man eigentlich nie. Also vielleicht habt ihr einen sehr, sehr kontinuierierten Workflow, wo euch völlig egal ist, was im globalen Namespace zugänglich ist, aber selbst da tut es eigentlich nicht weh, das weiter zu isolieren, um auf Nummer sicher zu gehen, dass es keine Interferenzen gibt, wenn ihr da doch noch was anderes drin laufen haben wollt. Würde ich also nie empfehlen, die Sache, die ich gerne nahe lege, wenn man pip mit minus minus user laufen lässt, dann installiert das Dinge nur für den aktuellen Unix, BSD, sonst was, User im Betriebssystem und macht die Bibliotheken für genau den zugänglich, das heißt, wenn ich als der betreffende User dann Python irgendwas ausführe, dann nimmt ja auch diese Bibliotheken mit rein, ohne zusätzliche Flex, ohne zusätzlichen Schnickschnack, das ist vor allem für alle Automatisierung und alles drumrum und alles Tooling total angenehm, alles schon weiß, dass es Unix-User gibt. Also, falls ihr das als System-D-Service laufen lasst, das hat schon ein User. Falls ihr Cronjobs einrichten wollt, da gibt es schon User und dann müsst ihr euch nicht mehr zusätzlich um irgendwas drumrum kümmern. Das ist nicht so riesig üblich, ich bin mir nicht ganz sicher, wieso möglicherweise, weil einige Leute einfach nicht wissen, dass es das gibt, was deshalb oft geraten wird, was auch nicht viel schlechter ist, sind Virtual Enves. Das ist im Prinzip dasselbe nur, dass kein User-Mechanismus dabei steckt. Also, es hat dann auch einen eigenen Python-Path und legt da die Bibliotheken ab, was man macht, dass man sucht sich die Virtual Env-Software der Wahl, ab Python 3 gibt es einfach VEnv, legt damit ein Virtual Env an, das sieht dann so aus, dass da ein Ordner ist, in dem alles ist, was zu diesem Python-Env gehört, den nennt man üblicherweise VEnv oder Env oder Punkt-Env und da drin findet man dann alle Bibliotheken, die installiert werden und ein Bin-Ordner und in dem Bin-Ordner liegt ein Activate-Script und immer bevor ihr mit diesem Python interagiert, müsst ihr das einmal ausführen. Das setzt dann die richtigen Environment-Variablen und macht auch sonst alles für euch. Das heißt halt auch, dass ihr in aller Automatisierung darauf achten müsst, dass ihr einmal Bin-Activate da ausführt und dann weitermacht, kann man halt immer mal vergessen und dann ist das etwas ätzend zu debagen. Das sagt da tatsächlich, ich konnte kein Django importieren. Na ja, hast du vielleicht vergessen, dein Virtual Env anzumachen. Also, so häufig ist diese Problemklasse. Ihr wollt dann auch Wage im Hinterkopf haben, wo diese verschiedenen Installationsmechanismen die Dependency ist hinlegen. Das ist immer irgendwie so ein Side-Packages, das unterschiedlich gut oder schlecht versteckt ist. Das ist super nützlich, um nachzugucken, welcher Code tatsächlich auf Platte liegt und was es wirklich läuft und was es wirklich los. Man braucht es nicht oft, aber wenn man es braucht, dann sucht man sich gerne ein Ast, bevor man dieses Side-Packages gefunden hat. Und die Installation selber, das ist in Pfeifen wie in den meisten dieser Skripsprachen, die dann irgendwann beschlossen haben, dass sie einen eigenen Paketmanager brauchen, eine etwas lange und verwahlene Geschichte. Früher gab es Easy Install und alles war ganz schlimm und dann war der Pip-Pile noch, aber hat sich noch nicht so irre durchgesetzt, deshalb rede ich jetzt erst mal über Pip, weil das wird so erst mal unterstützt. Pip-Install MyProject ist die entspannteste Variante, falls irgendwie die Leute, die euer Projekt zur Verfügung stellen, das fertig paketiert haben. Das ist nicht oft so, das ist bei sehr großen Projekten wie z.B. Prätix so, das kann man einfach installieren und dann ist es gut. Hoffentlich oft. Wenn man da irgendwie ein Archiv oder ein Getrepo hoffentlich oder so vor die Füße bekommen, wenn da drin eine Setup.py-Datei liegt, dann installiert man die mit Pip-Install-Punkt. Das sagt halt, das hier ist übrigens dein Paket. Und wenn nicht mal die drin liegt, dann liegt hoffentlich eine Requirements.txt da drin, die installiert man mit minus R Fahrt zur Datei. Dann kann man die Setup-Py-Datei ansehen. Die Requirements ist wirklich nur eine Liste dieser Requirements. In der Setup-Py gibt es ein Install-Requirements, das erklärt sich ziemlich von alleine, wo die Dependencies drinstehen. Auch wie die da drinstehen, ist ziemlich selbsterklärend. Im einfachsten Fall steht einfach nur ein String von drinnen, da ein Paket beschreibt. Im besten Fall steht da etwas mit Minerversion. Ist gleich irgendwas. Ihr wollt oder ich würde euch empfehlen, dass ihr darauf achtet, dass die Versionen zumindest halbwegs gepinnt sind, also das nicht etwas ganz ohne eine Version drinsteht. Im Python-Umfeld ist es sehr üblich, sich auf Semantic Versioning Semware zu verlassen oder das einzuhalten. Das heißt, Minerversion.minerversion.patch und es ist frei zum Upgrade zu lassen, sodass man entweder, keine Ahnung, Dependency ist größer, gleich, 5.3, aber kleiner, 5.4. Das heißt, alle Patch-Releases kommen mit oder noch lesbarer, gleich, 5.3. Stern. Das heißt halt, dass ihr im Zweifelsfall Security Patches über ein Upgrade-Prozess mitbekommt. Je nachdem, aber wie Paranoid, aber auf Stabilität sagt, ihr da seid, könnt ihr das auch komplett bis auf die Patch-Version festnageln. In jedem Fall solltet ihr falls da gar nichts gepinnt ist, auch wieder mit den Entwicklenden darüber reden, weil keine gute Idee. Also gerade in so ein Major Upgrade kommen halt gerne Sachen vorbei, die alles kaputt machen und das wollt ihr nicht. Genau, ansonsten, klar, ihr könnt da nachgucken, wenn Dinge kaputt gehen, was es möglicherweise sein kann, aber mehr solltet ihr damit hoffentlich nicht interagieren müssen. Die Einheitlichkeit dieses Ökosystems noch schlimmer ist an Sachen Installation, weil es gibt keinen absolut gar keinen einheitlichen Weg, Django-Projekte zu konfigurieren. Ganz am Ende ist die Source of Truth das Settings-Modul. Üblicherweise ist das einfach eine Settings.py, die irgendwo meistens so ein Verzeichnis hinter der Manage.py liegt. Das heißt, die ist nicht irgendwie komplexes Python, ihr könnt da einfach reingucken und nachgucken, was in diese Situation steht, um rauszufinden, was da Sache ist. Viele bieten an, eine Local Settings direkt daneben zu liegen und wenn die da ist, dann wird die importiert und überschreibt alles, was sie halt an Variablen setzt. Manchmal gibt es nichts, gar nichts, dann müsst ihr halt die Settings.py editieren. Da würde ich empfehlen, dass ihr dann auch einfach eine Local Settings.py daneben legt und die importiert, also versuche eine Local Settings.py zu importieren, neu setzen müsst und nicht die ganze Settings.py überschreiben. Das ist gerade bei einem Upgrade-Prozess ja doch etwas riskant. Es gibt Tools, die lesen irgendwelche Inny-Style, Conflicts ein. Es gibt Tools, die lassen sich nur über Environment-Variablen konfigurieren. Da müsst ihr echt mit den entwickelnden Reden und im Zweifelsfall auch einfach euren Bedarf anmelden. Das da ist nicht konfigurierbar, das brauche ich. Oder ich setze gerade jedes Mal 20 Environment-Variablen willst du nicht vielleicht irgendwas anderes dafür anbieten, wenn ich dieses Tool ausrollen muss. Das ist völlig verliebde. Ein Konfigurationsvariablen wie gesagt, könnt ihr nachher auch online nachgucken oder euch einfach wahr gemerkt, dass es da relevante Dinge gibt. Das muss nicht bis hinten lesbar sein. Die wichtigste, die ihr auf jeden Fall kontrollieren solltet, ist die Debug-Variable. Debug muss auf false stehen. Da führt einfach kein Weg dran vorbei. Sobald das in Produktion läuft, muss Debug false sein. Weil sonst, wenn der Server an irgendwas sich verschluckt, liefert der Stacktraces raus. In den Stacktraces stehen halt auch zu Hilfe für die Entwicklung. Lokale Variablen, das ist keine gute Idee. Django bemüht sich da sehr, sehr darum nicht blöd zu sein. Also die zensieren Passwörter weg. Die zeigen Datenbank-Passwörter und Secret Keys nicht an. Die zeigen auch sonstige Sachen an, die nicht aussehen, als könnten sie vielleicht sensible Daten sein, aber natürlich kann das nicht alles erwischen, also woher auch. Und deshalb, ja, Debug immer aus. Gar keine gute Idee. Es gibt eine Variable, die als Secret Key, die sollte, na, die weiße Secret sein, das heißt, wenn ihr das irgendwo von Github runterzieht und da steht schon Secret Key drin, solltet ihr den ändern. Der wird vor allem verwendet, um sowas wie Password Reset Tokens zu generieren, also fließt damit ein Video, um Session Signing zu machen und solche Sachen. Also es gibt meines Wissens keine aktiven Exploits, die direkt laufen, wenn man sonst alles richtig macht und nur das Secret Key rauskommt, aber ich meine, die Variable heißt Secret Key, also einfach Better Safe Than Sorry, die ist nicht für Publishment gedacht, also darauf achten. Es gibt die Allowed Hose, da schreibt ihr halt rein, unter welcher Tool am Ende laufen soll, ihr müsst irgendwie eine Datenbank konfigurieren, das, wie gesagt, hoffentlich stellt euch die Entwicklung dafür irgendein Mechanismus bereit, außer editiert halt diese Datei. Aber also auch das ist am Ende, man schreibt da halt einen Namen und ein User und ein Port und bla bla bla rein und am Ende verbindet man sich auf eine Datenbank. Und die Verzeichnisse, in denen am Ende die media- und statischen Dateien liegen, müsst ihr die Static Route und Media Route setzen, nicht Static Path und Media Path, was der Teil in der URL ist, unter dem das zu finden sein wird. Intuitives Naming. Daneben gibt es noch ein paar Sachen, die ihr setzen wollt, wenn das Ganze hinter einem normalen Web Server geproxied wird, wie ich es hier vorstelle und wie auch einfach so ein Sensibil Default für das Ausrollen von Web Anwendungen ist. Das ist vor allem, dass ihr in eurem Web Server ein Haufen Header setzt, die ihr dann da reinwerft, damit die Anwendung weiß, was eigentlich von draußen ursprünglich reinkam. Also ihr wolltet zum Beispiel sagen, Secure SSL redirect is false, weil ihr handelt hoffentlich das Upgrade auf SSL bei euch schon im Web Server, also im EngineX oder whatever. Und dafür setzt ihr dann hoffentlich ein HTT-PX forwarded host, um zu sagen, das kam als HTTPS rein. Denn die Entwicklung hat die Möglichkeit im Python Code zu sagen, war das mal ein Secure Request, um entsprechend Sachen zuzulassen oder nicht. Und dafür sollte es halt gesetzt sein. Für alle die Sachen, die ich hier nenne, gilt übrigens Header, die ihr bei euch im EngineX oder sonstwo setzt, solltet ihr vorher einmal droppen. Also nicht, dass da ein User ankommt ist. Also lieber auf Nummer sicher gehen und sicherstellen, dass niemand von außen so ein Header durchschmuggeln kann, weil keine Special Meanings auf den Headern. Und ansonsten ist es auch ganz nützlich, X forwarded host und X forwarded port mit reinzugeben. Also gerade der X forwarded host auf true zu setzen, ist sehr wichtig, weil es sagt Django, dass es diesem Header, also dem X forwarded host Header eher vertraut ist als ein Host Header, um zu wissen, an wen diese Request mal ging. Also Settings, Settings, Settings. Es gibt noch ein Bonus Setting, aber das ist sehr selten geredet wird, das müsst ihr auch entscheiden, ob ihr das wollt. Denkt auch ein bisschen davon ab, wie sehr ihr eure Entwicklerin da vertraut und euren Entwicklerinnen. Ihr könnt die admin Variable setzen und da eure Mailadresse und euren Namen reinlegen und dann noch ein paar andere Sachen. Also zu was für ein Mail Server sich das Ding verbinden kann und dann bekommt ihr immer, wenn der Server ein 500er ausliefert, eine Email mit dem Stacktrace. Wie gesagt, je nachdem, wie gut das programmiert ist, könnte das auch zu einer etwas größeren Anzahl von Emails führen. Da solltet ihr vielleicht ein Blick haben, aber es ist natürlich für euch sehr einfach dann zu sagen, hier, liebe entwickelnde, liebe GitHub Issuesystem, lieber wer auch immer schuld ist, hier ist ein Fehler aufgetreten und hier ist der Stacktrace, den ich noch um ein Haufen Variablen bereinigt habe. Es erleichtert das Debugging und das fixen dieser Fehler auf jeden Fall sehr. Ihr müsst dann noch eine Zeile in die Lock-Config auch in dieser Settings-Play hinzufügen. Das schreibe ich nachher noch ein. Hätte man hier eh nicht lesen können. Das habe ich mal drauf verzichtet, aber das ist eine sehr, sehr nützliche Angelegenheit. Einziges K-Wert, wenn ihr keine Emails bekommt, solltet ihr auf jeden Fall nochmal sicherstellen, dass diese Konfiguration korrekt ist, denn naheliegenderweise könnt ihr so eine nicht bekommen, wenn es keine E-Mails verschicken kann. Bin that on that. Und jetzt sind wir eigentlich auch schon fertig. Wir haben das ganze Ding aufgesetzt. Wir haben dependencies installiert. Wir wissen, wo Dateien liegen. Jetzt müssen wir nur noch dieses Python-Jungle dazu bringen, mit tatsächlich einen ehrlichen HTTB-Request zu reden, weil es kann es von Haus aus nicht direkt. Dafür gibt es das attraktiv benannte WISKI, WSGI. Und mehrere Tools, die das weiterleiten können. Es gibt vor allem Unicorn, das würde ich euch empfehlen, weil es sehr pflegeleicht ist. Es gibt daneben auch UWISKI. Wenn es funktioniert, möglicherweise unmerklich performanter, aber alle Leute, die jemals mit Problemen im Deployment zu uns kommen, also zu uns als Django Menschen benutzen UWISKI und während Unicorn sehr pflegeleicht das und einfach funktioniert. Und dann auch müsst ihr halt wissen, wie ihr gerne eure Services und eure Demons pflegt. Ich benutze meistens Systeme auf dem System, die irgendwie rumläuft und nehme dann SystemD Service Files. Wenn ihr was anderes nutzt, dann nehmt ihr das. Aber das ist im Prinzip sehr einfach. Man sagt, laufe als der richtige User, laufe im richtigen Directory und für Unicorn auf entweder diesem Socket oder diesem Port auch da wieder eure Präferenz, ob ihr lieber Port basiert, weiterleitet mit so und so vielen Worker aus. Fertig. Und dann läuft das. Ihr könnt da euren NGNX Apache, whatever, Randocken und alles sollte richtig funktionieren. Bei Default gibt es so ein bisschen Logging, gerade im Problemfall auf Standard Out, also in dem Fall dann im Syslog. Aber Logconfig müsste dann wirklich entweder nachlesen oder mit den entwickelnden Beschrechen denn das ist auch wieder etwas, da gibt es keinen Standard und alle machen das irgendwie anders und alle setzen irgendwie andere Loglevel und für unterschiedliche Funktionen und Bereiche. Das heißt, da muss man sich einmal absprechen, was aus eurer Sicht sinnvoll ist an Fehlern überhaupt zu sehen und auf welchem Medium. Also ihr könnt auch sagen, nur für diesen Teil und nur für dieses Loglevel möchte ich E-Mails bekommen oder in ein besonderes Verzeichnis loggen oder so. Genau, danach wollt ihr noch irgendwie so ein bisschen Maintenance betreiben, das gemäß ist ja der schlimmere Teil, weil man schon vergessen hat, was man vor fünf Monaten da irgendwo installiert hat oder möglicherweise auch vor zwei Jahren. Die Datenbank braucht hoffentlich sehr wenig Maintenance. Kann man einfach Migrate einspielen und in Sachen Backups braucht ihr an der Stelle auch nur die Datenbank. Also wie auch immer, ihr gerne eure Datenbank Backup, da reist völlig ein S-Rausdampen, S-Tar-GZ oder ihr benutzt geileren Mechanismen, die Postgres da so bereitstellt völlig euch überlassen. Aber in Sachen Backup in der Maintenance braucht ihr genau nur die Datenbank und die Mediapfiles, falls es in eurer Anwendung welche gibt, solltet ihr rausziehen. Wenn ihr ein sehr großer Fan von, ich möchte das direkt wieder irgendwo zum Laufen bringen und ich brauche reproducible builds und so seit, dann solltet ihr auch noch die vorhin genannten Side Packages wegspeichern, denn sofern eure Versionen nicht genau bis auf die Patch-Version gepinnt sind, bekommt ihr halt nicht unbedingt wieder die genau gleiche Version eurer Abhängigkeiten. Gleichzeitig müsst ihr da natürlich aufpassen, dass ihr auch wieder auf genau derselben Pipenversion lauft und so weiter, damit es problemfrei ist. Ich mach das in der Regel nicht, aber unterschiedliche Anforderungen brauchen unterschiedliche Sicherungsgrade. Ansonsten genau bei den Backups habe ich ja schon gesagt, ihr müsst Migrate laufen lassen, der tatsächliche Update-Mechanismus ist ein Pip-Install minus Groß-U. Das macht das richtige TM und die Fehlermeldungen sind auch meistens relativ benutzbar, also wenn es irgendwo Konflikte findet, dann sagt es euch das in lesbarem Englisch. Genau. Ihr migriert die Datenbank weiter, ihr lasst nochmal dieses Collect static laufen, wenn ihr es braucht, lasst ihr auch nochmal das Compressor zu laufen. Das ist alles in der Installation. Falls die Anwendung mehr als einer Sprache verfügbar ist, dann müsst ihr auch nochmal Compile-Messages laufen lassen, damit die magischen Übersetzungsstrings auch geupdated werden. Sonst bleiben die halt in jeder Sprache auf Englisch. Das fällt dann doch auf. Und das war's in Sachen Updates. Ihr wollt für eure eigene Convenience wahrscheinlich ein bisschen Cronjobs da rumliegen haben, die Entwicklungsabteilung welche, weil Django keinen eingebauten Scheduler oder so hat, das heißt, die sagen euch vielleicht hier einmal die Woche sollte das ausgeführt werden, um übrige Objekte in der Datenbank wegzuräumen oder so. Hoffentlich benutzen sie dafür den Django-Mechanismus, den es schon gibt, sodass ihr einfach Manage.py irgendwas ausführen könnt. Wenn sie das nicht machen, könnt ihr das auch ihnen empfehlen, sachte und freundlich. Das ist so clear Sessions ausführen. Das wird in sehr wenig Doku irgendwie erwähnt. Deshalb ist das hier quasi der Bonus-Tipp. Sonst fällt euch irgendwie in ein paar Monaten oder einem Jahr auf, dass eure Datenbank-Backups doch etwas größer werden und es liegt halt daran, dass lauter Sessions, die schon seit Monaten nicht mehr gültig sind, da immer noch drin rumliegen und nicht weggeräumt werden. Ihr könnt es auch einmal im Monat ausführen. Intervall ist nicht doll wichtig, aber ansonsten kann ich sehr empfehlen, die Django-Docs zu dem Thema anzugucken. Gerade die Settings sind gut dokumentiert, die verfügbaren Manage-Befäle sind super dokumentiert. Es gibt die schon gezeigte Release-Karte von, wie lange welches release gültig ist, das ist dokumentiert, welche Datenbank-Version mit welchem release gültig ist, die Dokumentation ist durchgehend versioniert, sodass ihr auch auf eure aktuelle Django-Version und dann auf die nächste springen könnt. Das ist natürlich der Job der Entwicklenden, aber einen Blick in die Release-Nodes werfen, ob da irgendwas groß drin steht von wegen beim Upgrade drauf achten, das und das umzuschreiben, das wird ja doch immer mal übersehen. Und ja, damit solltet ihr eigentlich sehr gut bedient sein. Es gibt einen sehr aktiven Django-Channel auf Free-Node, wo oft Leute hinkommen und auch mit ihren Diplomentproblemen ankommen und denen ganz gut weiter geholfen wird. Und ansonsten, die Django-Docs sind die besten Ressourcen und alle weiteren sind eigentlich entweder da oder spätestens im Agassi verlinkt. Und das war's, wenn ihr noch Fragen habt, haben wir jetzt ein bisschen Zeit dafür. Fragen? Ich laufe hier jetzt auch noch ein paar Tage rum nicht, also ihr könnt mich auch noch hinterhergreifen, aber aus der Entwicklerseite aus der Entwicklerseite zu Best Practices. Das ist echt schwer zu beantworten, weil Django ein sehr großes Thema ist. Es gibt einen Django-Style-Guide, der eigentlich für das Django-Projekt intern ist, von dem es überhaupt nicht wehtut, weil man den auch im eigenen Projekt anwendet. Ansonsten lohnt es sich sehr, einfach die von Django mitgelieferten Helferskripte zu benutzen, um zum Beispiel neue Module zu starten, also Start-App oder so, weil es einem schon eine Ordnung vorschlägt, die sehr, sehr sinnvoll ist. Aber darüber hinaus hängen die Best Practices sehr, sehr von der Größe der Anwendung ab und ändern sich dann. Also man merkt es, wenn die Anwendung eine gewisse Größe überschreitet, dann möchte man ändern, wie man bestimmte Sachen, zum Beispiel Template Rendering oder so, strukturell Hand habt. Es gibt dazu als beste Ressource, würde ich sagen, die Konferenzen. Es gibt Django-Kons in Europa und in den USA und in Australien. Und die Videos, die von da kommen, decken eine sehr große Bandbreite ab. Also da gibt es auch sehr, einfach Anfänger-Videos sind. Und wie fange ich mit Django an? Die kann man ja dann skippen. Aber es gibt da auch sehr schöne Talks von Leuten, die das halt für Projekte in sehr, sehr großer Größe einsetzen und welche Änderungen sie dann durchgenommen haben. Niemand sonst? Dann, danke für eure Aufmerksamkeit und wir können ja später noch ein bisschen darüber sprechen.