Poprzedni wykład     Lista wykładów     Następny wykład

Bazy danych

Obsługa baz danych w Django nie wymaga znajomości SQL. Będziemy pracować wyłącznie z obiektami w Pythonie.

Wybór SZBD Tworzenie tabel Wykorzystanie bazy danych na stronie

Wybór SZBD

Musimy poinformować serwer jaki SZBD (SZBD = System Zarządzania Bazą Danych) chcemy używać. W tym celu edytujemy plik settings.py: zmieniamy wartość zmiennej DATABASES, będącej słownikiem słowników, obowiązkowy jest tylko opis domyślnej bazy ('default'):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'rezerwacje' #zbieżność nazwy projektu i bazy danych jest nieistotna
    }
}

Konieczne jest także zarejestrowanie tworzonej właśnie aplikacji:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pensjonat.bookings'
)

Jeżeli wybierzemy inny SZBD, to słownik będzie musiał zawierać dodatkowe informacje: USER, PASSWORD, HOST, PORT,...

Żeby baza danych została utworzona i powiązana z projektem musimy wpisać polecenie:

python manage.py syncdb
Polecenie to będzie konieczne również po dodaniu nowej tabeli.

Po pierwszym poleceniu syncdb zostanie utworzona nowa baza danych, w niej Django utworzy kilka tabel związanych z użytkownikami, autoryzacją, zarządzaniem sesjami, itp. Zaproponuje również, by dopisać administratora (superuser w terminologii Django).

Spis treści

Tworzenie tabel

Każdą tabelę opisujemy jako klasę dziedziczącą po klasie django.db.models.Model. Definicje tych klas umieszczamy w pliku models.py. Lista dostępnych typów pól znajduje się tutaj. Zaczynamy od tabeli zawierającej listę apartamentów w pensjonacie.
from django.db import models

class Apartment(models.Model):
    bedrooms = models.SmallIntegerField()
    beds = models.SmallIntegerField()
    kitchenette = models.BooleanField()
    name = models.CharField(max_length=80,unique=True)
    pathToPicture = models.CharField(max_length=80)
Wygenerowany przez Django kod SQL tworzący tabelę możemy obejrzeć wpisując polecenie:
python manage.py sql bookings
BEGIN;
CREATE TABLE "bookings_apartment" (
    "id" integer NOT NULL PRIMARY KEY,
    "bedrooms" smallint NOT NULL,
    "beds" smallint NOT NULL,
    "kitchenette" bool NOT NULL,
    "name" varchar(80) NOT NULL UNIQUE,
    "pathToPicture" varchar(80) NOT NULL
)
;
COMMIT;
Nazwa tabeli różni się nieco od nazwy klasy. Do tworzonej tabeli zostało dodane pole id tworzące klucz główny. Wszystkie pola mają klauzulę NOT NULL, jest to ustawienie domyślne dla wszytkich typów pól (z wyjątkiem NullBooleanField). Pole dopuszczające wartość null możemy utworzyc tak:
test = models.SmallIntegerField(null=True)
Listę dostępnych opcji pól można znaleźć tutaj.

W Django nie wygodnego narzędzia do zmiany struktury tabel (ALTER TABLE ...). Dopisanie (usunięcie) kolumn w pliku models.py i wpisanie polecenia

python manage.py syncdb
nie zmieni struktury tabel. Jeżeli tabele nie zawierają jeszcze danych, to strukturę tabel można zmienić poleceniem:
python manage.py reset nazwa_aplikacji
Polecenie to wygeneruje polecenia SQL DROP TABLE ... i CREATE TABLE ....

Django dostarcza wygodnego narzędzia do modyfikacji zawartości utworzonej bazy danych (dodawanie, modyfikacja i usuwanie rekordów, przeglądanie tabel). Wpisujemy polecenie:

python manage.py shell
Uruchamia ono tekstową konsolę Pythona w trochę niestandardowy sposób, do zmiennej sys.path zawierającej listę katalogów przeszukiwanych po poleceniu importu, zostaje dodany katalog tworzonej aplikacji. Możemy zatem wpisać polecenie:
from bookings.models import *
Utworzenie obiektu i próba jego dopisania do tabeli:
a = Apartment()
a.save() =>
...
IntegrityError: bookings_apartment.bedrooms may not be NULL
Dopisanie nie powiodło się, bo wartość pola bedrooms wynosi NULL. (Wartość pozostałych pól, z wyjątkiem pola id, również wynosi NULL.)

Kolejna próba:

a = Apartment(bedrooms=2,beds=6,kichenette=True,name="nr 13",pathToPicture="")
print a.id => None
a.save()
print a.id => 1
Apartment.objects.count() => 1
a.delete()
Apartment.objects.count() => 0
Wartość polu id nadaje SZBD podczas dopisywania rekordu, SZBD gwarantuje również jednoznaczność tego pola. Pełną listę metod generujących zapytania do bazy danych można znaleźć tutaj.

Interaktywna praca z tabelami będzie znacznie wygodniejsza, jeśli rozbudujemy definicje klasy.

from django.db import models

class Apartment(models.Model):
    bedrooms = models.SmallIntegerField()
    beds = models.SmallIntegerField()
    kitchenette = models.BooleanField()
    name = models.CharField(max_length=80,unique=True)
    pathToPicture = models.CharField(max_length=80)
    def setFields(self,bedrooms,beds,name,kitchenette=True,pathToPicture=""):
        self.bedrooms = bedrooms
        self.beds = beds
        self.kitchenette = kitchenette
        self.name = name.strip()
        self.pathToPicture = pathToPicture.strip()
    def __str__(self):
        s = "Apartament: "+self.name+" (id="+str(self.id)+")\n"
        s+="Sypialnie: "+str(self.bedrooms)+"\n"
        s+="Miejsca: "+str(self.beds)+"\n"
        s+="Aneks kuchenny: "+("tak" if self.kitchenette else "nie")+"\n" 
        return s
Metoda strip obcina białe znaki z lewej i z prawej strony. Wykorzystanie dopisanych metod:
a = Apartment()
a.setFields(2,6,"nr 7")
a.save()
b = Apartment()
b.setFields(1,3,"nr 2")
b.save()
Apartment.objects.count() => 2
for a in Apartment.objects.all():
    print a
=>
Apartament: nr 7 (id=1)
Sypialnie: 2
Miejsca: 6
Aneks kuchenny: tak

Apartament: nr 2 (id=2)
Sypialnie: 1
Miejsca: 3
Aneks kuchenny: tak

Apartment.objects.get(id=1).delete()
for a in Apartment.objects.all():
    print a
=>
Apartament: nr 2 (id=2)
Sypialnie: 1
Miejsca: 3
Aneks kuchenny: tak
Modyfikację rekordu polegająca na zmianie wartości pola (pól) innego niż id można uzyskać tak:
a = Apartment.objects.get(id=2)
a.beds = 2
a.save()
for a in Apartment.objects.all():
    print a
=>
Apartament: nr 2 (id=2)
Sypialnie: 1
Miejsca: 2
Aneks kuchenny: tak
Wywołanie metody save() na rzecz obiektu, który już jest w bazie danych (ma nadany id) jest wykonaniem polecenia UPDATE ..., wywołanie tej metody na rzecz nowego obiektu jest wykonamiem polecenia INSERT ....

Spis treści

Wykorzystanie bazy danych na stronie

By wykorzystać bazę danych na stronie musimy: Spis treści
Poprzedni wykład     Lista wykładów     Następny wykład