Um ein Django-Projekt zu starten braucht es nicht immer viel, zumindest nicht so viel wie in manch anderem Tutorial als minimales Setup angegeben wird. Zum Verstaendnis von Django kann es imho jedoch praktisch sein, wenn man sich bewusst ist, wie wenig noetig ist, damit Django laeuft.

Vorweg: Ich finde es in Buechern und vielen Tutorials immer sehr anstrengend, wenn erst Mal Zeile fuer Zeile des Codes erklaert wird, ohne dass man eine Vorstellung vom Gesamt-Bild hat. Deswegen nicht wundern, wenn ich erst den Code praesentiere, dann das Ergebnis und danach erst beschreibe was da passiert.

Virtual Environment

Zu Erst erstellen wir uns ein Virtual Environment mit einer aktuellen Django-Version. Dazu verwende ich den Virtualenvwrapper, wobei jede andere Methode genau so gut funktioniert. Irgendwann(tm) werde ich sicherlich auch Mal genauer drauf eingehen, wie man die verschiedenen Moeglichkeiten nutzt und warum es generell gut ist ein Virtual Environment zu haben.

cp@venus:~$ mkvirtualenv -p /usr/bin/python3 helloworld
Running virtualenv with interpreter /usr/bin/python3
Using base prefix '/usr'
New python executable in helloworld/bin/python3
Also creating executable in helloworld/bin/python
Installing setuptools, pip...done.
(helloworld)cp@venus:~$ pip install Django
Downloading/unpacking Django
  Downloading Django-1.8.1-py2.py3-none-any.whl (6.2MB): 6.2MB downloaded
Installing collected packages: Django
Successfully installed Django
Cleaning up...

Minimales Script

Sobald wir unser Environment aufgesetzt haben, erstellen wir die Datei hello.py (oder ein anderer Name, da dieser hier keine Rolle spielt) mit folgendem Inhalt:

import sys

from django.conf import settings
from django.conf.urls import url
from django.http import HttpResponse


settings.configure(DEBUG=True, MIDDLEWARE_CLASSES=(), ROOT_URLCONF=__name__)


def index(request):
    return HttpResponse('Hello World')


urlpatterns = [url(r'', index)]


if __name__ == '__main__':
    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

Ergebnis

(helloworld)cp@venus:~$ python hello.py runserver
Performing system checks...

System check identified no issues (0 silenced).
May 07, 2015 - 20:05:53
Django version 1.8.1, using settings None
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

In einem anderen Terminal/Fenster oder im Browser kann man nun diese Seite aufrufen:

cp@venus:~$ curl -i http://127.0.0.1:8000/
HTTP/1.0 200 OK
Date: Thu, 07 May 2015 20:05:53 GMT
Server: WSGIServer/0.2 CPython/3.4.0
Content-Type: text/html; charset=utf-8

Hello World

Was passiert hier?

Zu den Imports gibt es nicht viel zu sagen, dann geht es mit folgender Zeile los:

settings.configure(DEBUG=True, MIDDLEWARE_CLASSES=(), ROOT_URLCONF=__name__)

Wir beginnen damit, dass wir DEBUG auf True setzen, womit wir unsere Anwendung in einen Debug-Modus versetzen, welcher uns mehr Details im Fehlerfall ausgibt. In Produktiv-Umgebungen, sollte dies nie genutzt werden. Nebenbei sparen wir uns so das Setzen der ALLOWED_HOSTS, welches in Produktiv-Umgebungen (DEBUG=False) immer gesetzt sein muss (weitere Informationen dazu).
MIDDLEWARE_CLASSES setzen wir explizit auf ein leeres Tupel, da wir keine Middleware-Module benoetigen und uns bei Django 1.7 und 1.8 eine Warnung darueber ersparen, dass sich die Standard-Werte fuer diese Liste geaendert hat.
Und zuletzt sorgen wir mit der Option ROOT_URLCONF dafuer, dass Django in der Datei nach den urlpatterns sucht.

def index(request):
    return HttpResponse('Hello World')

Dies ist unsere View bzw. das V in MVC (Model-View-Controller). Hier wird festgelegt, was dem Anwender praesentiert wird.
Django uebergibt dabei jeder View ein Request-Objekt und eventuell zusaetzliche Parameter, welche in der urlpatterns konfiguriert sind. Die Aufgabe der View ist es dann daraus eine Antwort zu generieren.

In der Regel wird diese Antwort in ein HTTP-Response-Objekt gepackt, bei dem wir in unserem Fall lediglich das "Hello World" als Content setzen. Der Status-Code (200) und der Content-Type (text/html) sind dabei Standard-Werte und koennen bei Bedarf geaendert werden.
Wie man im Quelltext der aufgerufenen Seite sehen kann werden jedoch keine HTML-Tags dazu geschrieben oder die Daten sonst wie geaendert.

urlpatterns = [url(r'', index)]

In den URL-Patterns wird die Zuordnung zwischen aufgerufenem Pfad und einer View geschaffen. In diesem Fall wird alles der oben definierten index-View zugeordnet. Durch die weiter oben gesetzte Einstellung ROOT_URLCONF weiss Django in welchem Modul es nach der urlpatterns suchen muss. Dabei kann sich die urlpatterns zwar prinzipiell ueberall befinden, muss jedoch so heissen. (Es gibt zwar Moeglichkeiten, wie dies auch noch umgangen werden kann, dafuer sollte man aber wissen was man tut.)

if __name__ == '__main__':
    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

Wer sich schon Mal die manage.py eines Django-Projektes angeschaut hat, dem duerftre dies recht bekannt vorkommen. Hier benutzen wir die gleiche Funktion wie in der manage.py um die Kommandozeilen-Optionen zu parsen und weiterzuverarbeiten.
Im Gegensatz zur manage.py haben wir jedoch kein DJANGO_SETTINGS_MODULE definiert, da wir die Konfiguration bereits selber vorgenommen haben.

Wofuer das Ganze?

Wie Eingangs bereits erwaehnt, hilft es beim Verstaendnis davon wie Django aufgebaut ist bzw. funktioniert. Da man besonders am Anfang von den ganzen verschiedenen Dateien erschlagen wird, wenn man ein Django-Projekt auf normalem Wege erstellt.

Auch wenn ich nicht kategorisch ausschliessen wuerde, dass es fuer 1-Datei Django-Projekte keine sinnvolle Einsatzmoeglichkeit gibt, faellt mir keine ein. Und spaetestens wenn es an Datenbank-Modelle geht wird es schnell unuebersichtlich.


Christian Prehl | 8. Mai 2015 | Tags: django hello world tutorial python