Aug. 17, 2008 Next × Previous Wiederverwendbare Django-Projekte

Eine der Stärken von Django ist die Wiederverwendbarkeit von einzelnen Applikationen (aka reusable apps). Will man aber ein komplettes Projekt veröffentlichen, sollte man sich auch Gedanken machen, wie man das komplette Projekt möglichst automatisch veröffentlichen kann. Anders ausgedrückt: der User soll möglichst wenig Pfade und Config-Einstellungen von Hand anpassen müssen.

Die verschiedensten Einstellungen eines Django-Projekts befinden sich in der Regel in der settings.py im Hauptverzeichnis deines Projekts, hier sind ein paar kleine Kniffe, wie du diese Einstellung möglichst dynamisch hälst:

Ein Hinweis zuvor: Die settings.py ist eine Python-Datei und wird auch von Python geparst. Es ist keine Ansammlung statischer Definitionen sondern in ihr kann auch eine komplette Programmlogik ausgelagert werden.

1. Dynamische Pfade

Die erste Notwendigkeit vor dem Deployment einer Seite ist es, die Pfade zu den Templates und den statischen Mediendateien anzupassen. Diese Arbeit können wir dem User abnehmen, indem wir sie von vornherein dynamisch festlegen. Grundlage allen ist es, erst einmal zu wissen, welcher Pfad zum Projektverzeichnis führt:

import os
PROJECT_ROOT = os.path.dirname(__file__)

Die Variable PROJECT_ROOT enthält damit den Pfad zum aktuellen Verzeichnis, sei es /var/www/meinprojekt/ oder unter Windows C:\Dokumente und Einstellungen\username\meinprojekt\.

Damit ist es möglich, die Pfade zu den Templates und den Mediendateien festzulegen. Eine Arbeit der der User vor dem Deployment also nicht mehr erledigen braucht:

MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'site_media')

TEMPLATE_DIRS = (
    os.path.join(PROJECT_ROOT, 'templates'),
)

2. Lass den SECRET_KEY geheim

Oft wird es vom User vergessen, den SECRET_KEY neu zu setzen. Er wird bspw. als Salt für die Passwort-Generierung benutzt. Am sichersten und einfachsten ist es für den User, den SECRET_KEY bei Bedarf sich selbst erstellen zu lassen: (Übernommen vom Byteflow-Projekt)

try:
    SECRET_KEY
except NameError:
    SECRET_FILE = os.path.join(PROJECT_ROOT, 'secret.txt')
    try:
        SECRET_KEY = open(SECRET_FILE).read().strip()
    except IOError:
        try:
            from random import choice
            SECRET_KEY = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
            secret = file(SECRET_FILE, 'w')
            secret.write(SECRET_KEY)
            secret.close()
        except IOError:
            Exception('Please create a %s file with random characters to generate your secret key!' % SECRET_FILE)

Der kleine Schnipsel prüft, ob eine Variable SECRET_KEY schon definiert wurde. Wenn nicht, erstellt er eine Datei secret.txt im Projektverzeichnis und schreibt darin selbstständig einen zufälligen String. (Der Webserver muss in diesem Fall Schreibrechte für das Projektverzeichniss besitzen.)

3. Don't touch the settings

In der Bildbearbeitung gibt es einen Leitsatz: Don't touch the Pixels. Das bedeutet, wenn man ein Bild bearbeiten will, legt man sich zuvor eine Kopie der Bildebene an oder erstellt einen Snapshot, um im Bedarfsfall auf die Originaldaten zurück greifen zu können.

Mit den Django-Settings verhält es sich ähnlich. Ich füge in alle meine Settings-Dateien am Ende diesen Schnipsel ein:

try:
    from local_settings import *
except ImportError:
    pass

Er versucht, eine Datei "local_settings.py" zu finden und übernimmt/überschreibt die Einstellungen aus dieser Datei in die globalen Einstellungen. Diese "local_settings.py" ist der perfekte Ort für die Einstellungen, die vom User in jedem Fall gesetzt werden müssen -- die Einstellungen für den Datenbankzugriff etwa.

Der große Vorteil kommt aber erst zum Tragen, wenn man das Projekt regelmäßig aus einem VCS aktualisiert. Da im Idealfall keine Daten in der ursprünglichen "settings.py" geändert werden, gibt es keine Kollisionen mit Updates. Der User kann also das Projekt regelmässig aus dem VCS aktualisieren, ohne jedes Mal die Einstellungen neu schreiben zu müssen.

Das waren drei kleine Kniffe, die das Deployment eines Projekts für den User sehr erleichtern. Das Ganze lässt sich noch beliebig fortführen, ist aber in den meisten Fällen projekt-abhängig. Hab ich noch etwas wichtiges vergessen, dann schreibt doch einen Hinweis in die Kommentare. :-)


  • Reply in this thread Kurushiyama Oct. 12, 2008

    Ich hatte das Problem, das os.path.dirname(__file__) einen leeren pfad zurückgab. Warum auch immer...

    Die Konstruktion: os.path.join(os.path.abspath(os.path.dirname(__file__)),'site_media', 'templates')

    löste das Problem.

    • Ubuntu 8.04
    • python 2.5.2
    • django 1.0
    1. Used for the gravatar, only!
    2. Look right
    3. or

Leave a comment

  1. Used for the gravatar, only!
  2. Look right
  3. or

↑ to the elevators

© 2001—2009 Martin Mahner. This is an I ♥ Django Project.

Admin | Generated: Sat, 4 Jul 2009 09:07:08 +0200