Installation von Django

Wir wollen nun das Django-Webframework auf unserem System installieren. Dazu benötigen wir Python >= 3.11.0, Django > ref.1 und eine virtuelle Umgebung.

Das Projekt, das wir in diesem Buch erstellen werden, wird ein webbasierter Event-Manager sein. Deshalb legen wir zuerst das Verzeichnis für das Projekt an. Mehr zu dem Projekt später mehr.

Grundsätzlich gibt es viele verschiedene Wege, eine Verzeichnisstruktur für ein Django-Projekt zu erstellen. Den Weg, den wir in diesem Buch gehen, ist ein altbewährter Weg und kapselt den Django-Quellcode nochmal in ein untergeordnetes Verzeichnis.

Python installieren

Wie man Python auf seinem System installiert, wird in unzähligen Tutorials im Web und in zahllosen Büchern ausführlich beschrieben. Ich gehe davon aus, dass dieser Schritt bekannt ist. Trotzdem an dieser Stelle noch ein Link, wie man Python der Pfad-Umgebungsvariable zufügt, falls das bei der Installation nicht gemacht wurde.

How to Add Python to PATH

In dem Artikel ist auch gut beschrieben, was Umgebungsvariablen überhaupt sind. Wer das noch nicht weiß, kann sich hier informieren. Wir werden Umgebungsvariablen später im Buch noch benötigen.

TIP: Um auf einem Linux/Unix-System komfortabel verschiedene Versionen von Python nutzen will, sollte sich mal pyenv angucken. Mit diesem Tool lässt sich jede beliebige Python-Version installieren und als global Python-Interpreter auswählen. Ein weiterer Vorteil dieses Ansatzes ist es, dass man nicht die System-Python-Version nutzen muss.

Eine Beschreibung, wie das geht, findet sich in diesem Artikel von realpython.com: Managing Multiple Python Versions With pyenv

Django-Projektverzeichnis anlegen

Wir wollen alle Django-Projekte zentral in einem Verzeichnis auf unserem Rechner verwalten. Dazu legen wir an einem geeigneten Ort ein neues Verzeichis namens django_projects an und wechseln in das neu angelegte Verzeichnis:

mkdir django_projects && cd django_projects

Unser Projekt wird ein Event-Manager werden. Das Projektverzeichnis dazu legen wir ebenfalls im django_projects Verzeichnis an.

mkdir event_project

Dieses Verzeichnis ist das Projektverzeichnis, in dem neben unserem Django-Projekt auch alles abgelegt wird, was nicht direkt mit dem Django Quellcode zu tun hat. Zum Beispiel die README.md-Datei, die .gitignore und ähnliches. Hier wird später mit git init das Git-Repository erstellt und (bei Bedarf) die docker-compose.yml-Datei angelegt.

Erstellen wir die README.md und die .gitignore schonmal. Wir werden diese Dateien später benötigen, wenn wir das Projekt mit git versionieren.

Alle Pfad-Angaben in diesem Tutorial beziehen sich auf dieses Verzeichnis.

Aktuelle Verzeichnis-Struktur

Unsere aktuelle Verzeichnis-Struktur sollte jetzt so aussehen:

├── django_projects
    └── event_project
        ├──  README.md
        ├── .gitignore

Virtuelle Umgebung anlegen

Wir wollen alle unseren virtuellen Umgebungen an einem zentralen Ort verwalten. Dazu legen wir innerhalb der django_projects ein Verzeichnis .envs für die virtuellen Umgebungen an. Wir erstellen auch gleich eine virtuelle Umgebung namens eventenv für unseren Event-Manager.

Für diese Aufgabe nutzen wir das Python-Modul venv, welches in der Python Standard Library enthalten ist und nicht extra installiert werden muss.

python -m venv .envs/eventenv

venv hat uns praktischerweise auch gleich ein Verzeichnis .envs angelegt und dort das Environment eventenv installiert. Das Verzeichnis django_projects sieht nun so aus:

├── django_projects
    └── event_project
        ├──  README.md
        ├── .gitignore
    └── .envs
        └──eventenv

Warum benötigt man denn ein virtuelles Environment?

Ziel eines virtuellen Environments ist das Isolieren der für ein Projekt benötigten Python-Pakete und Module. Um in einem Projekt ein andere Version eines Moduls zu nutzen als ein einem anderen Projekt, ist es nötig, diese voneinander zu isolieren. Virtuelle Environments sind in Python der klassische Weg, dies zu erreichen.

Good Practice

Es hat sich bewährt, virtuelle Umgebungen an einem zentralen Ort und nicht innerhalb der einzelnen Projekte zu verwalten. Deshalb haben wir das .envs-Verzeichnis in den django_projects angelegt.

Es sollte vermieden werden, virtuelle Verzeichnisse innerhalb von Django-Projekte anzulegen, da sonst zum Beispiel die Gefahr besteht, dass sie versioniert werden.

Noch mehr Isolation

Das Isolieren von Python-Projekten mit einem virtuellen Environment ist die einfachste Möglichkeit, dies zu tun. In der Praxis werden Projekte heute aber in der Regel durch Containerisierung (zb. Docker) oder virtuellen Maschinen isoliert, um auch zusätzliche Software wie Datenbanken oder Webserver vom Host-System zu isolieren.

Ziel dieser Virtualisierungen ist, dass alle am Projekt beteiligten Entwickler die exakt gleichen Umgebungen haben. Eine virtuelle Umgebung alleine kann dies nicht leisten.

Virtuelle Umgebung starten

Unter Windows starten wir die virtuelle Umgebung wie folgt:

cd django_projects
.envs\eventenv\Scripts\activate

Unter Linux/OSX/Unix müssen wir leicht abgeändert schreiben:

$ cd django_projects
$ source ./envs/eventenv/bin/activate

Wenn alles geklappt hat, erhalten wir nun den Präfix eventenv (bzw. der Name des gewählten Environments) auf der Shell. Mit deactivate kann man das Environment wieder verlassen.

(eventenv) deactivate

Was GENAU ist ein virtuelles Environment eigentlich?

Eine virtuelle Umgebung ist ein Verzeichnis, in dem der Python-Interpreter, die Bibliotheken und die Skripte, die darin installiert sind, von denen isoliert sind, die in anderen virtuellen Umgebungen oder im Systempfad installiert sind. Durch Manipulation der PATH-Umgebungsvariable wird diese Python-Version aufgerufen, wenn ein Programm gestartet wird und nicht die Python-Systeminstallation.

Ein kleiner Test auf der Linux-Shell beweist uns das. Wir gucken uns die PATH-Umgebungsvariable mit deaktiviertem Environment an:

echo $PATH | tr ":" "\n"
/usr/local/sbin
/usr/local/bin
/usr/bin
..

Die Python-Systeminstallation befindet sich in diesem FAll unter usr/bin, und wenn jetzt auf der Shell python eingetippt wird, sucht das Betriebssystem alle Pfade durch, bis das Programm python gefunden wird.

Jetzt das gleiche Experiment nochmal mit aktiviertem Environment:

source .envs/eventenv/bin/activate
(eventenv) echo $PATH | tr ":" "\n"
/home/solaris/django_projects/.envs/eventenv/bin
/usr/local/sbin
/usr/local/bin
/usr/sbin
..

Wie wir sehen können, hat die virtuelle Umgebung nun den Pfad zu sich selbst ganz am Anfang der PATH-Variable geschoben. Bei jedem Aufruf von python wird dieser Pfad nun zuerst gefunden und genutzt. Man kann problemlos in zwei Shells unterschiedliche Environments nutzen.

Wer wissen möchte, wie ein virtuelles Environment hinter den Kulissen funktioniert, dem sei dieser Artikel hier ans Herz gelegt:

https://realpython.com/python-virtual-environments-a-primer

Django installieren

Nun ist es an der Zeit, Django zu installieren. Wir werden alle Pakete, die wir im Laufe des Projekts nutzen wollen, nicht direkt mit pip installieren, sondern alle Dependencies schön säuberlich in eine Text-Datei schreiben, die dann später mit pip installiert werden kann. Der große Vorteil bei diesem Vorgehen ist, dass andere Entwickler, die das Programm nutzen wollen, so eine einfache Möglichkeit haben, das Programm zu starten. Das gilt als best practice und sollte nicht anderes gemacht werden, wenn in einem Python-Programm Drittanbieter-Module genutzt werden.

Wir nutzen allerdings pip nicht direkt, sondern pip-tools, um neue Pakete komfortabel und sicher zu managen.

Was ist pip-tools?

pip-tools ist ein kleines Helferprogramm, welches uns Entwicklern hilft, unsere Dependencies zu verwalten.

Der große Vorteil gegenüber dem klassischen Weg mit einer requirements.txt-Datei ist, dass durch die Aufspaltung in eine requirements.in und eine requirements.txt die Entwickler-Intention hinsichtlich des Pinnens von Versionen besser zur Geltung kommt.

In der requirements.in gibt der Entwickler (gepinnt oder nicht), das Paket an, das er benötigt, und in der von pip-tools kompilierten requirements.txt liegen die von pip-tools gepinnten und aufgelösten Abhängigkeiten. Das ist ziemlich nice. Falls eine Abhängigkeit nicht aufgelöst werden kann, bricht der Kompilierungsvorgang ab.

Die Requirements-Dateien kommen in das Django-Rootverzeichnis, welches für unser Projekt noch nicht existiert. Unser Projekt wird eine Event-Managemener und deshalb nennen wir das Projektverzeichnis event_manager

Dieses Verzeichnis legen wir jetzt an und erstellen dort die requirements.in sowie die requirements-dev.in

├── django_projects
       └── event_project
         └── event_manager
           └── requirements.in
           └── requirements-dev.in
       └── README.md
       └── .gitignore
       └── .envs
           └──eventenv

Was es mit diesen beiden Dateien genau auf sich hat, sehen wir gleich.

Pip-tools bietet zwei wichtige Kommandos.

  • pip-compile erstellt aus einer requirements.in eine requirements.txt-Datei und nimmt die Dependency-Auflösung vor

  • pip-sync installiert die Pakete auf dem Rechner

Pip-tools Installation

Piptools muss in jedem Environment erstmal installiert werden. Wir installieren es in unser gerade eben erstelles eventenv.

(eventenv) pip install pip-tools

Requirements und Requirements-dev

Wir wollen gleich von Anfang an darauf achten, dass wir für unsere Live-und Entwicklungsumgebung zwei seperate Dateien anlegen. Damit verhindern wir, dass später Module und Pakete in der Live-Umgebung landen, die dort nicht hingehören, wie zb. die Debug-Toolbar.

Requirements.txt erstellen mit pip-compile

Die nötigen Pakete, die wir für unser Projekt benötigen, werden von uns in die requirements.in bzw. requirements-dev.in Dateien geschrieben, je nachdem, ob wir das Paket nur lokal oder auch im Produktivbetrieb benötigen.

Die Versionsauflösung übernimmt pip-tools für uns. Unter der Haube läuft das mit pip. In die requirements.in fügen wir folgenden Eintrag ein:

django==stable.3

In der Datei requirements-dev.in werden nur die Abhängigkeiten aufgelistet, die neben der Produktion auch für die Entwicklung erforderlich sind, zum Beispiel Tools zum Debuggen der Applikation. Hier listet der Befehl -c requirements.txt alle in der Datei requirements.in genannten Abhängigkeiten auf.

Wir schreiben in die requirements-dev.in:

-c requirements.txt

Mehr zu pip-tools in der Doku: https://github.com/jazzband/pip-tools

Unser Verzeichnis sollte nun so aussehen:

├── django_projects
       └── event_project
         └── event_manager
           └── requirements.in
           └── requirements-dev.in
       └── README.md
       └── .gitignore
       └── .envs
           └──eventenv

Um aus den dot.in - Dateien die endgültigen Requierements-Dateien zu machen, müssen diese mit pip-compile kompiliert werden.

(eventenv)  pip-compile requirements.in
(eventenv)  pip-compile requirements-dev.in

Nach dem Kompilieren sollten wir im Verzeichnis die beiden requirements.txt Dateien sehen:

├── django_projects
       └── event_project
         └── event_manager
           └── requirements.in
           └── requirements.txt
           └── requirements-dev.in
           └── requirements-dev.txt
       └── README.md
       └── .gitignore
       └── .envs
           └──eventenv

Pakete installieren mit pip-sync

Danach können die Pakete im Environment installiert werden. Wichtig ist, dass die beiden Dateien in einem Kommando gesynct werden. Ansonsten überschreibt nämlich immer das letzte das davorige.

(eventenv)  pip-sync requirements.txt requirements-dev.txt

Django wurde nun für dieses Environment installiert. Prüfen können wir das mit aktiviertem Environment und dem Befehl pip freeze.

requirements.txt

Die requirements.txt ist eine gute Möglichkeit, den Überblick über die installierten Python-Module in einem Projekt zu behalten. Es handelt sich dabei um eine einfache Textdatei, in der eine Liste der Module und Pakete gespeichert wird, die für unser Projekt erforderlich sind. Mit Pip-tools konnten wir den Vorgang noch weiter vereinfachen und nutzen pip-compile, um aus einer requirements.in eine requirements.txt zu erstellen.

Übrigens lässt sich die von pip-tools erstellte requirements.txt auch ganz normal mit pip installieren, wenn man nicht pip-sync nutzen will.

Um Pakete mit pip-tools zu updaten, führt man upgrade aus

(eventenv) pip-compile requirements.in --upgrade
(eventenv) pip-compile requirements-dev.in --upgrade
(eventenv)  pip-sync requirements.txt requirements-dev.txt

Good Practice

Django ist ein Python-Package wie jedes andere auch. Auch wenn es für den Anfänger am Anfang etwas umständlich erscheinen mag, wird für jedes Projekt, dass wir erstellen werden, eine eigene virtuelle Umgebung und eine eigene Django-Installation erstellt. Wir können somit gewährleisten, dass alle zusätzlichen Module mit ihren Versionen nur für dieses eine Projekt gelten, und nicht für alle Projekte, die wir erstellen wollen.

Pip Freeze

Mit dem Befehl pip freeze können wir uns die derzeit im aktuellen Environement installierten Packages und Module anzeigen lassen (die Versionen werden höchstwahrscheinlich bei Dir abweichen. Das macht aber nichts):

(eventenv) pip freeze
asgiref==3.stable
Django==stable.6
pytz==2021.1
sqlparse==0.stable

Django Version

Wenn wir wissen wollen, welche Django-Version installiert wurde, können wir das prüfen, in dem wir die interaktive Python-shell starten, Django importieren und die Methode get_version() aufrufen.

(eventenv) python
Python 3.10.2 (main, May 17 2022, 02:19:35) [GCC 9.ref] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.get_version()
'stable.10'

Noch einfacher geht es mit diesem Befehl in der Konsole:

(eventenv) python -m django --version

Mehr zum Thema Installation von Django findet sich in der Doku: