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.4 Erstellung der Applikation  topZur vorigen Überschrift

Ein Projekt ist nur der Rahmen für eine Webseite. Die eigentliche Funktionalität wird durch sogenannte Applikationen implementiert, die in das Projekt eingebunden werden können. Genau wie für Projekte bietet Django auch für Applikationen ein Werkzeug an, mit dem das Grundgerüst einer Applikation erzeugt werden kann.

Um unsere News-Applikation zu erzeugen, wechseln wir mit einer System-Shell in das Projektverzeichnis und führen den nachstehenden Befehl aus (das python am Anfang kann unter Windows entfallen):

$ python manage.py startapp news

Dabei ist news der gewünschte Name der neuen Applikation.

Das Programm erzeugt in unserem Projektverzeichnis einen neuen Ordner namens news, der drei Dateien enthält (siehe Abbildung 25.4).

Abbildung 25.4  Ordner einer neuen Django-Applikation

Die Datei __init__.py ist wie bei Projekten deshalb notwendig, damit die Applikation ein importierbares Python-Modul wird. Sie ist standardmäßig leer.

Interessanter sind die beiden anderen Dateien, models.py und views.py, die dazu dienen, das Django zugrunde liegende Model-View-Konzept umzusetzen (siehe Abbildung 25.5).

Abbildung 25.5  Das Model-View-Konzept

Das sogenannte Model definiert die Struktur unserer Daten und wie damit umgegangen werden muss. Außerdem bieten Models eine komfortable Schnittstelle für den Zugriff auf die gespeicherten Daten. Wie die konkrete Kommunikation mit der Datenbank vonstatten geht, bleibt dem Programmierer verborgen. Er kann beim Umgang mit den Daten auf die Schnittstellen des Models zurückgreifen, ohne sich um technische Details wie SQL-Statements kümmern zu müssen. [Natürlich ist es möglich, eigene SQL-Befehle an die Datenbank zu senden, falls die mächtige API von Django für einen speziellen Fall nicht ausreichen sollte. In der Praxis werden Sie allerdings höchstwahrscheinlich niemals darauf zurückgreifen müssen. ] Die Datenbank selbst bleibt ihm »verborgen«, weil er sie nur indirekt durch das Model »sieht«.

Die sogenannte View (dt. Sicht) kümmert sich um die Aufbereitung der Daten für den Benutzer. Sie kann dabei auf die Models zurückgreifen und deren Daten auslesen und verändern. Wie dabei die Benutzerschnittstelle konkret aussieht, ist der View egal. Die Aufgabe der Views ist nur, die vom Benutzer abgefragten Daten zu ermitteln, diese zu verarbeiten und dann an ein sogenanntes Template zu übergeben, das die eigentliche Anzeige übernimmt. Mit Templates werden wir uns später beschäftigen.

Ein Model definieren

Der erste Schritt nach der Erstellung einer neuen Applikation ist die Definition eines Datenmodells. Diese Definition sieht so aus, dass für alle Arten von Datensätzen, die die Applikation braucht, eine Klasse erstellt wird. Diese Klassen müssen von der Basisklasse models.Model im Paket django.db abgeleitet werden und legen die Eigenschaften der Datensätze und ihre Verknüpfungen untereinander fest.

Unser Beispielmodell für die News-Applikation definiert eine Modellklasse für die Meldungen und eine für die Besucherkommentare. Wir schreiben die Definition in die Datei models.py, die dann Folgendes enthält:

from django.db import models 
 
class Meldung(models.Model): 
    titel = models.CharField(max_length=100) 
    zeitstempel = models.DateTimeField() 
    text = models.TextField("Meldungstext") 
 
class Kommentar(models.Model): 
    news = models.ForeignKey(Meldung) 
    autor = models.CharField(max_length=70) 
    text = models.TextField("Text")

Die Attribute der Datensätze werden über Klassenmember festgelegt, wobei jedes Attribut eine Instanz eines speziellen Feldtyps von Django sein muss. Über die Parameter der Feldtyp-Konstruktoren werden dabei die Eigenschaften der Attribute angegeben.

Die Klasse Meldung besitzt ein CharField namens titel, das eine maximale Länge von 100 Zeichen haben soll. Der Feldtyp CharField dient zum Speichern von Texten begrenzter Länge. Das Attribut zeitstempel soll den Veröffentlichungszeitpunkt jeder Meldung angeben und benutzt den für Zeitangaben gedachten Feldtyp DateTimeField. Im letzten Attribut namens text wird der eigentliche Meldungstext gespeichert. Der verwendete Feldtyp TextField kann beliebig lange Texte speichern.

Die beiden Attribute autor und text der Klasse Kommentar speichern den Namen desjenigen Besuchers, der den Kommentar geschrieben hat, und den Kommentartext selbst. Interessanter ist das Attribut meldung, das eine Beziehung zwischen den Meldungen und Kommentaren herstellt.

Beziehungen zwischen Modellen

Es ist so, dass es zu einer Meldung mehrere Kommentare geben kann und dass sich umgekehrt jeder Kommentar genau auf eine Meldung bezieht. Mit dem Feldtyp ForeignKey (dt. Fremdschlüssel) wird eine One-To-Many Relation (dt. Eins-zu-viele-Relation) festgelegt, die besagt, dass es zu einem Kommentar genau eine Meldung gibt.

Abbildung 25.6  One-To-Many Relation bei Meldung und Kommentar

Neben den One-To-Many Relations unterstützt Django auch Many-To-Many (dt. Viele-zu-vielen) und One-To-One Relations (dt. Eins-zu-eins-Relation), die wir aber nicht thematisieren werden.

Wir sind nun mit der Definition des Models fertig und können Django anweisen, eine entsprechende Datenbank anzulegen. Vorher müssen wir allerdings unsere Applikation noch in das Projekt einbinden. Dies wird dadurch erreicht, dass wir den Modulnamen der Applikation in das Tupel INSTALLED_APPS am Ende der settings.py unseres Projekts einfügen:

INSTALLED_APPS = ( 
    'django.contrib.auth', 
    'django.contrib.contenttypes', 
    'django.contrib.sessions', 
    'django.contrib.sites', 
    'unser_projekt.news' 
)

Das Tupel INSTALLED_APPS enthält dabei die Importnamen aller Applikationen, die das Projekt verwendet. Sie werden sich jetzt wundern, warum unser eigentlich leeres Projekt schon vier Applikation enthält. Django bindet diese Applikationen standardmäßig ein, weil sie in eigentlich jedem Projekt gebraucht werden.

Nachdem wir nun unsere Applikation erzeugt, ihr Datenmodell definiert und sie in das Projekt eingefügt haben, können wir die Datenbank erstellen. Wir rufen hierzu das Programm manage.py mit dem Parameter syncdb auf:

$ python manage.py syncdb 
Creating table auth_message 
Creating table auth_group 
Creating table auth_user 
Creating table auth_permission 
Creating table django_content_type 
Creating table django_session 
Creating table django_site 
Creating table news_meldung 
Creating table news_kommentar

Django erzeugt anhand der Model-Definition automatisch die passenden SQL-Statements für die verwendete Datenbank. Für jede Modellklasse wird eine eigene Tabelle angelegt, die Spalten für alle Attribute der Klasse enthält. Die Namen der Spalten entsprechen dabei den Attributnamen. Zusätzlich gibt es in jeder Tabelle eine Spalte namens id, mit der jeder Datensatz eindeutig über eine Ganzzahl identifiziert werden kann. [Sie können auch eigene id-Spalten definieren. Nähres finden Sie in der Django-Dokumentation. ]

Nachdem die notwendigen Tabellen in der Datenbank erzeugt worden sind, fragt uns das Script, ob wir einen Benutzeraccount für die Administrationsoberfläche anlegen möchten. Wir beantworten die Frage mit »yes« und geben entsprechende Daten ein. Natürlich sollten Sie an dieser Stelle andere Zugangsdaten wählen als im Beispiel.

You just installed Django's auth system, which means you don't have any superusers defined. 
Would you like to create one now? (yes/no): yes 
Username (Leave blank to use 'revelation'): Johannes 
E-mail address: je@revelation-soft.de 
Password: 
Password (again): 
Superuser created successfully.

Die Model-API

Bevor wir uns mit der automatisch generierten Administrationsoberfläche auseinandersetzen, wollen wir das Model-API kennenlernen, mit dem wir auf die Daten unseres Models zugreifen können. Das Programm manage.py kann mit dem Parameter shell in einem Shell-Modus gestartet werden, in dem wir über eine interaktive Python-Shell unsere Models verwenden können.

Anlegen von Datensätzen

Zuerst wollen wir die Shell nutzen, um eine News-Meldung in die Datenbank zu schreiben:

$ python manage.py shell 
>>> from unser_projekt.news.models import Meldung, Kommentar 
>>> from datetime import datetime 
>>> m = Meldung(titel="Unsere erste Meldung", 
                zeitstempel=datetime.now(), 
                text="Klassischerweise steht hier 'Hallo Welt'.") 
>>> m.save()

Mit diesem einfachen Code wurde eine neue Meldung erzeugt und auch schon in der Datenbank abgelegt. Da sowohl das Projekt aus auch die Applikation einfache Python-Module sind, können wir sie über ein import-Statement einbinden.

Um neue Datensätze zu erzeugen, müssen wir nur die dazugehörige Model-Klasse instanziieren. Der Konstruktor der Model-Klasse erwartet dabei Schlüsselwortparameter für alle Attribute des Datensatzes. Wichtig ist außerdem, dass Django für jeden Spaltenwert einen Wert mit einem Datentyp erwartet, der zu der Spaltendefinition passt. Deshalb muss für den Umgang mit Datumsangaben der Typ datetime.datetime importiert werden. Für die Textspalten sind Strings passend.

Sie können auf die Attribute einer Model-Instanz auf gewohnte Weise zugreifen und sie auch über Zuweisungen verändern:

>>> m.titel 
'Unsere erste Meldung' 
>>> m.titel = "'Hallo Welt'-Meldung" 
>>> m.save() 
>>> m.id 
1

Mit der letzten Abfrage m.id greifen wir auf die automatisch von Django eingefügte id-Spalte des Models zu. Da es sich bei m um den ersten Eintrag handelt, hat m.id den Wert 1.

Kommentare können wir direkt über die jeweilige Meldung einfügen. Durch die Bindung der Kommentar-Klasse an die Meldung bekommt jede Meldung-Instanz ein Attribut kommentar_set, das Zugriff auf die Kommentare der Meldung bietet:

>>> m2 = Meldung(titel="Umfrage zu Django", 
                zeitstempel=datetime.now(), 
                text="Wie findet ihr das Framework?") 
>>> m2.save() 
>>> k1 = m2.kommentar_set.create(autor="Heinz", text="Super!") 
>>> k2 = m2.kommentar_set.create(autor="Jens", text="Klasse!") 
>>> m2.kommentar_set.count() 
2 
>>> m2.save()

Nun gibt es eine zweite Meldung in unserer News-Tabelle, die bereits mit zwei Kommentaren versehen ist. Das erste m2.save() ist deshalb erforderlich, da erst beim Speichern ein id-Spaltenwert von der Datenbank erzeugt wird, um Kommentare mit dem Datensatz zu verknüpfen.

Es gibt noch eine unschöne Stelle in unserem Modul, die wir beheben sollten. Schauen Sie sich einmal an, was Python ausgibt, wenn wir eine Meldung-Instanz ausgeben lassen:

>>> m2 
<Meldung: Meldung object>

Diese Form der Darstellung ist nicht sehr nützlich, da sie uns keine Informationen über den Inhalt des Objekts liefert. Sie können in der models.py jeder Klasse eine Methode namens __unicode__ angeben, die eine aussagekräftige Repräsentation des Objektinhalts zurückgeben sollte. Wir ändern unsere models.py so ab, dass die __unicode__-Methoden der Klassen Meldung und Kommentar jeweils das kennzeichnende Attribut text zurückgeben:

class Meldung(models.Model): 
    ... 
    def __unicode__(self): 
        return self.text 
 
class Kommentar(models.Model): 
    ... 
    def __unicode__(self): 
        return self.text

Damit die Änderungen auch für unsere Shell wirksam werden, müssen wir sie neu starten. Sie beenden dazu einfach den Python-Interpreter mit der Tastenkombination + oder + und starten ihn dann erneut. Dabei sollten Sie nicht vergessen, nach dem Neustart auch wieder die Model-Klassen und datetime zu importieren.

Wenn wir nun in der neuen Shell eine Meldung erzeugen, können wir sie auch in sinnvoller Weise ausgeben lassen:

>>> m = Meldung(titel="Nun auch mit guten Ausgaben", 
                zeitstempel=datetime.now(), 
                text="Jetzt sehen die Ausgaben auch gut aus.") 
>>> m 
<Meldung: Jetzt sehen die Ausgaben auch gut aus.> 
>>> m.save()

Sie sollten nach Möglichkeit alle Ihre Model-Klassen mit einer __unicode__-Methode ausstatten, da Django oft darauf zurückgreift, um Informationen zu den Objekten auszugeben.

Abfrage von Datensätzen

Mittlerweile wissen Sie, wie man neue Datensätze in die Datenbank eines Django-Projekts einfügt. Genauso wichtig wie das Anlegen neuer Datensätze ist aber auch das Abfragen von Datensätzen aus der Datenbank. Für den Zugriff auf die bereits in der Datenbank vorhandene Datensätze bietet jede Model-Klasse ein Attribut namens objects an, dessen Methoden ein komfortables Auslesen von Daten ermöglichen:

>>> Meldung.objects.all() 
[<Meldung: Klassischerweise steht hier 'Hallo Welt'.>, 
 <Meldung: Wie findet ihr das Framework?>, 
 <Meldung: Jetzt sehen die Ausgaben auch gut aus.>]

Mit der all-Methode von Meldung.objects können wir uns eine Liste [Es handelt sich bei dem Rückgabewert von all nicht um eine Liste im Sinne einer Instanz des Datentyps list. Tatsächlich wird eine Instanz des Django-eigenen Datentyps QuerySet zurückgegeben, der sich nach außen aber fast genauso wie list-Instanzen verhält. ] mit allen Meldungen in der Datenbank zurückgeben lassen. Wirklich interessant sind aber die Methoden get und filter des objects-Attributs, mit denen sich gezielt Datensätze ermitteln lassen, die bestimmte Bedingungen erfüllen. Die gewünschten Bedingungen werden bei den Abfragen als Schlüsselwort-Parameter übergeben. Wird mehr als eine Bedingung angegeben, verknüpft Django sie automatisch mit einem logischen UND.

Mit get lassen sich einzelne Datensätze abfragen. Sollten die geforderten Bedingungen auf mehr als einen Datensatz zutreffen, wirft get eine AssertException. Wird kein passender Datensatz gefunden, quittiert get dies mit einem DoesNot Exist-Fehler. Wir nutzen get, um unsere Umfrage-Meldung aus der Datenbank zu lesen:

>>> umfrage = Meldung.objects.get(titel="Umfrage zu Django") 
>>> umfrage.kommentar_set.all() 
[<Kommentar: Super!>, <Kommentar: Klasse!>]

Wie Sie sehen, liest Django den entsprechenden Datensatz nicht nur aus der Datenbank, sondern erzeugt auch eine passende Instanz der dazugehörigen Model-Klasse, die sich anschließend genauso verwenden lässt, als sei sie gerade erst von uns erzeugt worden.

Field Lookups

Mit der Methode filter können wir auch mehrere Datensätze auf einmal auslesen, sofern sie den übergebenen Kriterien entsprechen:

>>> Kommentar.objects.filter(meldung__id=2) 
[<Kommentar: Super!>, <Kommentar: Klasse!>]

Bei dieser Abfrage liefert Django alle Kommentar-Datensätze, die mit einer Mel dung verknüpft sind, deren id-Attribut den Wert 2 hat. Diese Art der Abfrage ist deshalb möglich, weil Django in der Lage ist, Verknüpfungen auch über mehrere Tabellen hinweg zu »folgen«. Der doppelte Unterstrich wird dabei als Trennung zwischen Objekt und Unterobjekt betrachtet, ähnlich dem Punkt in der Python-Syntax. Diese Art der Bedingungsübergabe wird auch von get unterstützt.

Der doppelte Unterstrich kann neben der Abfrage über die Verknüpfungen von verschiedenen Model-Klassen hinweg auch zur Verfeinerung normaler Bedingungen genutzt werden. Dazu wird einem Schlüsselwortparameter der doppelte Unterstrich, gefolgt von einem speziellen Namen, nachgestellt. Mit dem folgenden filter-Aufruf können Sie beispielsweise alle Umfragen ermitteln, deren text-Attribut mit der Zeichenfolge "Jetzt" beginnt:

>>> Meldung.objects.filter(text__startswith="Jetzt") 
[<Meldung: Jetzt sehen die Ausgaben auch gut aus.>]

Diese Art der verfeinerten Abfrage wird in Django Field Lookup (dt. Feldnachschlagen) genannt. Alle Field Lookups werden in der Form attribut__lookup typ=wert an die Methode filter übergeben. Django definiert sehr viele und teilweise spezielle Field-Lookup-Typen, weshalb die folgende Tabelle nur als Einblick zu verstehen ist:


Tabelle 25.2  Eine Übersicht über die wichtigsten Field-Lookup-Typen
Field-Lookup-Typ Erklärung

exact

Prüft, ob das attribut genau gleich wert ist. Dies ist das Standardverhalten, wenn kein Field Lookup angegeben wird.

iexact

Wie exact, aber es wird nicht zwischen Groß- und Kleinschreibung unterschieden.

contains

Prüft, ob attribute den Wert von wert enthält.

icontains

Wie contains, aber es wird nicht zwischen Groß- und Kleinschreibung unterschieden.

gt

Prüft, ob attribut größer als wert ist. (gt: engl. Greater Than)

gte

Prüft, ob attribut größer als oder gleich wert ist. (gte: engl. Greater Than or Equal)

lt

Prüft, ob attribut kleiner als wert ist. (lt: engl. Lower Than)

lte

Prüft, ob attribut kleiner als oder gleich wert ist. (lte: engl. Lower Than or Equal)

in

Prüft, ob attribut in der für wert übergebenen Liste ist:

Meldung.objects.filter(id_in=[1, 2])

startswith

Prüft, ob der Wert von attribut mit wert beginnt.

istartswith

Entspricht startswith, aber es wird nicht zwischen Groß- und Kleinschreibung unterschieden.

endswith und iendswith

Wie startswith und istartswith, aber auf das Ende von attribut bezogen.

range

Prüft, ob attribut in dem Bereich ist, der von dem zweielementigen Tupel wert definiert wird:

Meldung.objects.filter(id_range=(1, 3))


Abfragen auf Ergebnismengen

Die filter-Methode gibt eine Instanz des Datentyps QuerySet zurück. Das Besondere an dem Datentyp QuerySet ist, dass man auf seinen Instanzen wiederum die Methoden für den Datenbankzugriff ausführen kann. Auf diese Weise lassen sich sehr komfortabel Teilmengen von Abfrageergebnissen erzeugen.

Beispielhaft ermitteln wir zuerst die Menge aller Kommentare, deren zugehörige Meldung den Titel "Umfrage zu Django" hat. Anschließend extrahieren wir aus der Menge die Meldungen, deren Text "Super!" lautet:

>>> k = Kommentar.objects.filter(meldung__titel="Umfrage zu Django") 
>>> k 
[<Kommentar: Super!>, <Kommentar: Klasse!>] 
>>> k.filter(text="Super!") 
[<Kommentar: Super!>]

Sie sollten sich am besten vor dem Weiterlesen durch »Herumspielen« mit dem Model-API vertraut machen, weil es eine Schlüsselkomponente für den Umgang mit Django darstellt.



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