.. _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:** * ``_ * ``_