.. _installation:
.. index::
single: Installation von Django
single: PATH
single: virtuelle Umgebung
single: Umgebungsvariablen
single: pip-tools
single: pyenv
single: requirements.txt
single: pip
single: Dependency Management
single: Produktivumgebung
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:
.. code-block:: bash
mkdir django_projects && cd django_projects
Unser Projekt wird ein Event-Manager werden. Das ``Projektverzeichnis`` dazu legen wir ebenfalls im ``django_projects`` Verzeichnis an.
.. code-block:: bash
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:
.. code-block:: shell
├── 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.
.. code-block:: shell
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:
.. code-block:: shell
├── 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.
.. admonition:: 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.
.. admonition:: 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:
.. code-block:: shell
cd django_projects
.envs\eventenv\Scripts\activate
Unter Linux/OSX/Unix müssen wir leicht abgeändert schreiben:
.. code-block:: shell
$ 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.
.. code-block:: shell
(eventenv) deactivate
.. admonition:: 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:
.. code-block:: shell
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:
.. code-block:: shell
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:
``_
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``
.. code-block:: shell
├── 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``.
.. code-block:: shell
(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:
.. code-block:: shell
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``:
.. code-block:: shell
-c requirements.txt
**Mehr zu pip-tools in der Doku:**
``_
Unser Verzeichnis sollte nun so aussehen:
.. code-block:: shell
├── 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.
.. code-block:: shell
(eventenv) pip-compile requirements.in
(eventenv) pip-compile requirements-dev.in
Nach dem Kompilieren sollten wir im Verzeichnis die beiden requirements.txt Dateien sehen:
.. code-block:: shell
├── 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.
.. code-block:: shell
(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``.
.. admonition:: 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
.. code-block:: shell
(eventenv) pip-compile requirements.in --upgrade
(eventenv) pip-compile requirements-dev.in --upgrade
(eventenv) pip-sync requirements.txt requirements-dev.txt
.. admonition:: 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):
.. code-block:: shell
(eventenv) pip freeze
.. code-block:: shell
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.
.. code-block:: shell
(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:
.. code-block:: shell
(eventenv) python -m django --version
**Mehr zum Thema Installation von Django findet sich in der Doku:**
* ``_
* ``_