Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by haas.homelinux.net...

Inhaltsverzeichnis
1 Einleitung
2 Überblick über Python
3 Die Arbeit mit Python
4 Der interaktive Modus
5 Grundlegendes zu Python-Programmen
6 Kontrollstrukturen
7 Das Laufzeitmodell
8 Basisdatentypen
9 Benutzerinteraktion und Dateizugriff
10 Funktionen
11 Modularisierung
12 Objektorientierung
13 Weitere Spracheigenschaften
14 Mathematik
15 Strings
16 Datum und Zeit
17 Schnittstelle zum Betriebssystem
18 Parallele Programmierung
19 Datenspeicherung
20 Netzwerkkommunikation
21 Debugging
22 Distribution von Python-Projekten
23 Optimierung
24 Grafische Benutzeroberflächen
25 Python als serverseitige Programmiersprache im WWW mit Django
26 Anbindung an andere Programmiersprachen
27 Insiderwissen
28 Zukunft von Python
A Anhang
Stichwort

Download:
- ZIP, ca. 4,8 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Python von Peter Kaiser, Johannes Ernesti
Das umfassende Handbuch - Aktuell zu Python 2.5
Buch: Python

Python
gebunden, mit CD
819 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1110-9
Pfeil 25 Python als serverseitige Programmiersprache im WWW mit Django
  Pfeil 25.1 Installation
  Pfeil 25.2 Konzepte und Besonderheiten im Überblick
  Pfeil 25.3 Erstellen eines neuen Django-Projekts
  Pfeil 25.4 Erstellung der Applikation
  Pfeil 25.5 Djangos Administrationsoberfläche
  Pfeil 25.6 Unser Projekt wird öffentlich
  Pfeil 25.7 Djangos Template-System
  Pfeil 25.8 Verarbeitung von Formulardaten


Galileo Computing - Zum Seitenanfang

25.7 Djangos Template-System  topZur vorigen Überschrift

Unsere bisher implementierten Views sind noch alles andere als optimal: Erstens sind sie optisch wenig ansprechend, da nur einfacher Text ausgegeben wird, und außerdem werden sie direkt aus String-Konstanten in der View-Funktion erzeugt. Besonders im zweiten Punkt muss noch nachgebessert werden, da es eines der Hauptziele von Django ist, die Komponenten eines Projekts möglichst unabhängig voneinander zu gestalten. Im Optimalfall kümmert sich die View-Funktion nur um die Verarbeitung der Parameter und die Abfrage und Aufbereitung der Daten. Die Erzeugung der Ausgabe für den Browser sollte einem anderen System übertragen werden, das sich wirklich nur um die Ausgabe kümmert.

Hier kommen sogenannte Templates (dt. Schablonen) ins Spiel, die darauf spezialisiert sind, aus übergebenen Daten ansprechende Ausgaben zu generieren. Im Prinzip handelt es sich bei Templates um Dateien, die Platzhalter enthalten. Wird ein Template mit bestimmten Werten für die Platzhalter aufgerufen, werden die Platzhalter durch eben diese Werte ersetzt, und als Ergebnis enthält man die gewünschte Ausgabe. Neben einfachen Ersetzungen von Platzhaltern unterstützt das Template-System von Django auch Kontrollstrukturen wie Fallunterscheidungen und Schleifen.

Bevor wir uns mit der Definition von Templates selbst beschäftigen, werden wir das Einbinden von Templates in View-Funktionen besprechen.

Django kapselt das gesamte Template-System in seinem Untermodul django.template. Mit der Klasse loader dieses Moduls können wir eine Template-Datei laden und daraus ein neues Template-Objekt erzeugen. Der Werte für die Platzhalter in dem Template werden über einen sogenannten Kontext übergeben, der über die Klasse Context erzeugt werden kann.

Einbinden von Templates in View-Funktionen

Angenommen, wir hätten bereits ein Template mit dem Dateinamen meldungen.html definiert [Wie Sie angeben können, wo Django nach den Templates suchen soll, wird gleich besprochen. ] , dann könnten wir unsere meldungen-View folgendermaßen anpassen:

from unser_projekt.news.models import Meldung, Kommentar 
from django.http import HttpResponse 
from django.template import Context, loader 
def meldungen(request): 
    template = loader.get_template("news/meldungen.html") 
    context = Context({"meldungen" : Meldung.objects.all()})
return HttpResponse(template.render(context))

Durch diese Anpassung ist die View-Funktion meldungen auf winzige drei Zeilen geschrumpft. [Man kann sich auf den Standpunkt stellen, dass so einfach gestrickte View-Funktionen ebenfalls überflüssig sind. Django bietet dafür sogenannte Generic Views (dt. allgemeine Ansichten) an. Näheres dazu finden Sie in der Django-Dokumentation. ]

Mit der get_template-Methode der loader-Klasse laden wir das gewünschte Template. Dann erzeugen wir einen Kontext, der die Liste aller Meldungen mit dem Platzhalter "meldungen" verknüpft. Die endgültige Ausgabe des Templates für den erzeugten Kontext generieren wir mit der render-Methode und übergeben das Ganze als Parameter an HttpResponse. Die Änderung des Kontext-Typs nach "text/plain" entfällt, da unsere Templates im Folgenden HTML-Code erzeugen werden.

Nun können wir uns mit dem Template meldungen.html selbst befassen.

Die Template-Sprache von Django

Django implementiert für die Definition von Templates eine eigene Sprache. Die ist so ausgelegt, dass damit jeder beliebige Ausgabedatentyp erzeugt werden kann, solange er sich als Text ausdrücken lässt. Es bleibt also Ihnen überlassen, ob Sie einfachen Text, HTML-Quelltext, XML-Dokumente oder andere textbasierte Dateitypen generieren.

Bevor Sie allerdings mit Templates arbeiten können, müssen Sie Django mitteilen, wo es nach den Template-Dateien suchen soll. Dazu müssen Sie in der settings.py Ihres Projekts die Pfade zu allen Ordnern angeben, unter denen Sie Ihre Templates ablegen wollen. Wir erstellen der Einfachheit halber einen Ordner templates in unserem Projektverzeichnis und tragen den Pfad in die settings.py ein:

TEMPLATE_DIRS = ( 
    "C:/unser_projekt/templates" 
)

Beachten Sie dabei, dass Sie für die Trennung der Pfadkomponenten immer den Forward-Slash / und nie den Backslash \ verwenden sollten – selbst dann, wenn Sie unter Windows arbeiten.

Sie sollten der Übersichtlichkeit halber die Templates für jede Applikation Ihres Projekts in einem eigenen Ordner ablegen. Für die Templates unserer News-Applikation legen wir deshalb einen Unterordner namens news im Verzeichnis templates an.

Nun können wir eine Datei meldungen.html anlegen, die folgenden Template-Code enthält: [Bitte beachten Sie, dass hier bewusst wegen der Übersichtlichkeit auf wichtige HTML-Elemente verzichtet wurde, wodurch der HTML-Code nicht mehr den Standards entspricht. Sie sollten natürlich in Ihren eigenen Programmen nur gültige HTML-Dateien erzeugen. ]

<h1>News-&Uuml;bersicht</h1> 
 
{% for n in meldungen.objects.all %} 
  <div class="kontainer"> 
    <div class="titelzeile"> 
      <div class="titel">{{ n.titel|escape }}</div> 
      <div class="zeitstempel">{{ n.zeitstempel }}</div> 
      <div style="clear: both"></div> 
    </div> 
    <div class="text"> 
      {{ n.meldung|escape|linebreaksbr }} 
      <div class="link_unten"> 
        <a href="{{ n.id }}/">Details</a> 
      </div> 
    </div> 
  </div> 
{% endfor %}

Im Prinzip ist das Template eine einfache HTML-Datei, die durch spezielle Anweisungen der Template-Sprache ergänzt wird. In dem Beispiel wurden alle Stellen, an denen Djangos Template-Sprache zum Einsatz kommt, fett markiert.

Im Folgenden werden wir die markierten Stellen unter die Lupe nehmen.

Variablen ausgeben

Der Zugriff auf Elemente des verwendeten Kontextes geschieht über doppelte geschweifte Klammern. Mit {{ meldung.titel }} wird dabei beispielsweise das Attribut titel der Kontext-Variable meldungen ausgegeben. Wie Sie sehen, kann bei der Ausgabe mit {{ ... }} auch der Punkt verwendet werden, um auf die Attribute von Kontext-Variablen zuzugreifen.

Wenn Django bei der Verarbeitung eines Templates auf eine Angabe wie {{ variable.member }} stößt, versucht es, die Daten in folgender Weise zu ermitteln:

1. Zuerst wird versucht, wie bei einem Dictionary mit variable["member"] einen Wert zu finden.
2. Schlägt dies fehl, wird versucht, den Wert mit variable.member auszulesen.
3. Wenn auch das nicht funktioniert, versucht Django, die Methode vari able.member() aufzurufen, und schreibt deren Rückgabewert an die Stelle.
4. Bei einem Fehlschlag wird probiert, member als einen Listenindex zu interpretieren, indem mit variable[member] ein Wert gelesen wird. (Dies geht natürlich nur, wenn member eine Ganzzahl ist.)
5. Wenn alle diese Versuche scheitern, nimmt Django den Wert, der in der settings.py für TEMPLATE_STRING_IF_INVALID gesetzt wurde. Standardmäßig ist dies ein leerer String.
       
Filter für Variablen

Sie können das Ersetzen von Kontextvariablen durch sogenannte Filter anpassen. Ein Filter ist eine Funktion, die einen String verarbeiten kann, und wird so verwendet, dass man der Variable bei ihrer Ausgabe einen senkrechten Strich, gefolgt vom Filternamen, nachstellt:

{{ variable|filter }}

Es ist auch möglich, mehrere Filter hintereinander zu übergeben. Sie werden dabei einfach, durch einen senkrechten Strich getrennt, hintereinander geschrieben:

{{ variable|filter1|filter2|filter3 }}

In dem Beispiel würde zuerst filter1 auf den Wert von variable angewandt, das Ergebnis an filter2 übergeben und dessen Rückgabewert schließlich mit filter3 verarbeitet.

Django implementiert eine ganze Reihe solcher Filter. In der folgenden Tabelle sind die beiden Filter erklärt, die in unserem Beispiel Verwendung finden:


Tabelle 25.3  Zwei der Filter von Django
Filter Bedeutung

escape

Ersetzt die Zeichen <, >, &, " und ' durch entsprehende HTML-Kodierungen.

linebreaksbr

Ersetzt alle Zeilenvorschübe durch das HTML-Tag <br/>, das eine neue Zeile erzeugt.


Im Übrigen ist es auch möglich, eigene Filter zu definieren. Informationen dazu und eine ausführliche Übersicht mit allen Django-Filtern finden Sie in der Dokumentation.

Tags

Djangos Template-Sprache arbeitet mit sogenannten Tags (dt. Kennzeichnungen), mit denen Sie den Kontrollfluss innerhalb eines Templates anpassen können. Jedes Tag hat die Form {% tag_bezeichnung %}, wobei tag_bezeichnung von dem jeweiligen Tag abhängt. Es gibt auch Tags, die einen Block umschließen. Solche Tags haben die folgende Struktur:

{% block test_block %} 
    Inhalt des Tags 
{% endblock }

Es existieren Tags, mit denen sich Kontrollstrukturen (wie die bedingte Ausgabe oder die wiederholte Ausgabe eines Blocks) abbilden lassen.

Der if-Block dient dazu, einen bestimmten Teil des Templates nur dann auszugeben, wenn eine Bedingung erfüllt ist:

{% if besucher.hat_geburtstag % } 
    Herzlichen Glückwunsch zum Geburtstag! 
{% else %} 
    Willkommen auf unserer Seite! 
{% endif %}

Wenn besucher.hat_geburtstag den Wahrheitswert True ergibt, wird dem Besucher der Seite zum Geburtstag gratuliert. Ansonsten wird er normal begrüßt, was über den else-Zweig festgelegt wird. Natürlich kann der else-Zweig auch entfallen.

Als Bedingung können auch komplexe logische Ausdrücke gebildet werden:

{% if bedingung1 and bedingung2 and bedingung3%} 
    Es gelten bedingung1 und bedingung2 und/oder es gilt 
    bedingung3 
{% endif %}

Neben den Fallunterscheidungen gibt es auch ein Äquivalent zu Python-Schleifen: das for-Tag. Das for-Tag ist dabei eng an die Syntax von Python angelehnt und kann beispielsweise so aussehen:

{% for zahl in ganzzahlen %} 
    {{ zahl }} ist eine Ganzzahl. 
{% endfor %}

Diese Schleife funktioniert natürlich nur dann, wenn die Kontextvariable ganzzahlen auf ein iterierbares Objekt verweist.

Hätte ganzzahlen den Wert [1, 2, 3], würde das obige Template folgende Ausgabe produzieren:

1 ist eine Ganzzahl 
2 ist eine Ganzzahl 
3 ist eine Ganzzahl

Als Letztes werden wir die sogenannte Vererbung bei Templates besprechen.

Es kommt häufig vor, dass viele Seiten einer Webanwendung das gleiche Grundgerüst aus beispielsweise Kopfzeile und Navigation besitzen. Wenn aber jede Seite ein eigenes Template hat, müsste dieses Grundgerüst redundant in allen Templates enthalten sein. Dies geht zu Lasten der Wartbarkeit.

Um dieses Problem zu lösen, kann man das Grundgerüst der Seite in einem zentralen Template definieren und von diesem zentralen Template die konkret benötigten Templates ableiten.

Angenommen, das Template in der Datei basis.html enthält das Grundgerüst der Webseite, kann ich ein anderes Template mithilfe des extends-Tags davon ableiten:

{% extends "basis.html" %}

Dies hat zur Folge, dass der komplette Inhalt von basis.html in das erbende Template eingefügt wird. Damit ein erbendes Template auch den Inhalt der entstehenden Seite selbst bestimmen kann, kann ein Template sogenannte Blöcke mit dem block-Tag definieren.

Ein Block ist dabei eine Stelle innerhalb eines Templates, die mit einem Namen versehen wird und durch erbende Templates mit konkretem Inhalt versehen werden kann.

Betrachten wir zwei Beispieldateien:

basis.html

---------- Kopfzeile ------------ 
{% block inhalt %}Standardinhalt{% endblock %} 
---------- Fußzeile -------------

Wenn Sie dieses Template mit Django ausgeben lassen, wird das block-Tag einfach ignoriert und durch seinen Inhalt ersetzt:

---------- Kopfzeile ------------ 
Standardinhalt 
---------- Fußzeile -------------

Interessant wird es dann, wenn wir ein anderes Template von basis.html erben lassen:

erbendes_template.html

{%extends "basis.html" %} 
 
{% block inhalt %}Hallo, ich habe geerbt!{% endblock}

Die Ausgabe von erbendes_template.html sieht dann so aus:

---------- Kopfzeile ------------ 
Hallo, ich habe geerbt! 
---------- Fußzeile -------------

Natürlich ist ein Grundgerüst einer Seite nicht die einzige Anwendung für die Template-Vererbung. Sie können Vererbung immer dann einsetzen, wenn mehrere Seiten auf einer gemeinsamen abstrakten Struktur basieren sollen.

Mit diesem Wissen können wir nun ein ansprechendes HTML-Template-Gefüge für unser Webprojekt erstellen. In einer Datei basis.html werden wir das Grundgerüst der Seite mitsamt den CSS-Stylesheets [Cascading Style Sheets (CSS) ist eine Formatierungssprache, um beispielsweise HTML-Seiten optisch aufzuwerten. ] ablegen. Die Datei basis.html hat den folgenden Inhalt, wobei aus Gründen der Übersichtlichkeit auf die Angabe von einigen Teilen verzichtet wurde:

<?xml version="1.0" ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
  <title>Unsere Django-Seite</title> 
  <link rel="stylesheet" type="text/css" href="styles.css" /> 
  <style type="text/css"> 
    /* Hier kommen die CSS-Styles hin */ 
  </style> 
</head> 
<body> 
  <div id="inhalt"> 
    <h2>{% block titel %}Django Beispielseite{% endblock %}</h2>
{% block inhalt %} {% endblock %} </div> </body> </html>

Das Template definiert eine einfache HTML-Seite, in der es zwei Template-Blöcke gibt: titel und inhalt. Diese Blöcke sollen nun von den Templates für die Meldungsübersicht und die Meldungsdetails mit Inhalt gefüllt werden.

Die Datei meldungen.html, in der das Template für die Meldungsübersicht definiert werden soll, sieht dann folgendermaßen aus:

{% extends "news/basis.html" %}
{% block titel %}News-&Uuml;bersicht{% endblock %}
{% block inhalt %} {% for n in object_list %} <div class="kontainer"> <div class="titelzeile"> <div class="titel">{{ n.titel|escape }}</div> <div class="zeitstempel">{{ n.zeitstempel }}</div> <div style="clear: both"></div> </div> <div class="text"> {{ n.meldung|escape|linebreaksbr }} <div class="link_unten"> <a href="{{ n.id }}/">Details</a> </div> </div> </div> {% endfor %} {% endblock %}

Wenn Sie die Dateien in dem template/news/-Verzeichnis im Projektordner gespeichert haben, können Sie das Ergebnis in Ihrem Browser betrachten [Die vollständige basis.html-Datei inklusive aller CSS-Styles finden Sie auf der Buch-CD. ] (siehe Abbildung 25.13).

Wenn Sie auf dieser Seite den Details-Link anklicken, gelangen Sie natürlich weiterhin zu der tristen Textansicht der jeweiligen Meldung. Um dies zu ändern, werden wir auch die View-Funktion meldung_detail umstricken:

def meldung_detail(request, meldungs_id): 
    template = loader.get_template("news/meldung_detail.html")
meldung = get_object_or_404(Meldung, id=meldungs_id) kontext = Context({"meldung" : meldung})
return HttpResponse(template.render(kontext))

Abbildung 25.13  Schicke HTML-Ausgabe unseres ersten Templates

Ihnen wird sicherlich aufgefallen sein, dass sich die beiden Views meldungen und meldung_detail strukturell sehr stark ähneln: Zuerst wird ein Template geladen, dann der Kontext über ein Dictionary erzeugt und schließlich ein HTTPResponse-Objekt zurückgegeben, das den Rückgabewert von template.render enthält.

Um Schreibarbeit zu sparen, bietet Django für solche Fälle eine Shortcut-Funktion render_to_response an. Mit render_to_response können wir die beiden View-Funktionen noch einmal verkürzen:

def meldungen(request): 
    return render_to_response("news/meldungen.html", 
        {"meldungen" : Meldung.objects.all()}) 
 
def meldungen_detail(request, meldungs_id): 
    return render_to_response("news/meldung_detail.html", 
        {"meldung" : get_object_or_404(Meldung, id=meldungs_id)})

Der Shortcut-Funktion render_to_response wird der Pfad zu dem gewünschten Template als erster und das Dictionary mit dem Kontext als zweiter Parameter übergeben.

Um unsere HTML-Ausgabe zu komplettieren, fehlt nur noch das Template für die Detailseite unserer Meldungen:

{% extends "news/basis.html" %}
{% block titel %} News-Details f&uuml;r Eintrag {{ meldung.id }} {% endblock %}
{% block inhalt %} <div class="kontainer"> <div class="titelzeile"> <div class="titel">{{ meldung.titel|escape }}</div> <div class="zeitstempel">{{ meldung.zeitstempel }}</div> <div style="clear: both"></div> </div> <div class="text"> {{ meldung.text|escape|linebreaksbr }} </div> </div>
<div class="kontainer"> <div class="titelzeile">Kommentare</div> {% if meldung.kommentar_set.count %} <table> {% for k in meldung.kommentar_set.all %} <tr class="kommentarzeile"> <td class="spaltenbezeichner">{{ k.autor }}:</td> <td>{{ k.text|escape|linebreaksbr }}</td> </tr> {% endfor %} </table> {% else %} Keine Kommentare {% endif %} </div>
<div class="link_unten"><a href="../">Zur&uuml;ck</a></div> {% endblock %}

Im Browser stellt sich das Ganze dann so dar wie in Abbildung 25.14.

Abbildung 25.14  Detailseite einer Meldung mit zwei Kommentaren

Wir sind nun so weit, dass wir ansprechende Ausgaben mit wenig Aufwand erzeugen können. Unser Projekt ist damit fast fertiggestellt. Es fehlt nur noch die Möglichkeit für die Besucher der Seite, Kommentare zu den Meldungen abgeben zu können.

Damit werden wir uns im letzten Abschnitt über Django befassen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  
  Zum Katalog
Zum Katalog: Python






Python
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux






 Linux


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Praxisbuch Web 2.0






 Praxisbuch Web 2.0


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Praxisbuch Objektorientierung






 Praxisbuch Objektorientierung


Zum Katalog: Einstieg in SQL






 Einstieg in SQL


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo