Django: Databázový model

Databáze je základem každého většího webu. Django umožňuje vytvářet databázové modely a pracovat s jejich daty pomocí ORM přístupu. Abychom si to mohli vyzkoušet, představíme si větší aplikaci, kterou budeme postupně budovat.

Seriál: Hrajeme si s Djangem (16 dílů)

  1. Django: Úvod a instalace 14.8.2009
  2. Django: Nastavení projektu a první pokusy 21.8.2009
  3. Django: Databázový model 28.8.2009
  4. Django: Databázový model podruhé 4.9.2009
  5. Django: Administrace 11.9.2009
  6. Django: Prezentace dat 18.9.2009
  7. Django: Prezentace dat podruhé 25.9.2009
  8. Django: Zpracovávání formulářů 2.10.2009
  9. Django: Autentizace a autorizace 9.10.2009
  10. Django: Nahrávání souborů 16.10.2009
  11. Django: Zabudované aplikace 23.10.2009
  12. Django: Rozšiřování možností Djanga 30.10.2009
  13. Django: Internacionalizace 6.11.2009
  14. Django: Nasazování projektu 13.11.2009
  15. Django: Kešování a škálování 20.11.2009
  16. Django: Závěr 27.11.2009

Pokud chceme manipulovat s daty, což znamená je vytvářet, načítat, upravovat a mazat (anglicky create, read, update and delete, často zkracováno jako CRUD), je potřeba použít nějaké úložiště dat. Relační databáze je příkladem takového úložiště a Django je uzpůsobeno pro její využití, stačí ho jen správně nastavit.

Propojení s databází

Opět se nejprve ponoříme do editování souboru settings.py, který obsahuje několik konstant, začínajících prefixem DATABASE_. Ty nastavují propojení Djanga s danou databází. Jak jste se již mohli dočíst v úvodním seznámení, Django podporuje více databázových serverů a my si vybrali databázi SQLite (verze 3), protože je velice jednoduchá na nastavení — stačí změnit pouhé dvě konstanty:

DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = '/home/dqd/hrajeme_si/sqlite.db' 

Konstanta DATABASE_ENGINE určuje databázový systém, který hodláme v projektu používat. Dále máme na výběr: 'postgresql_psycopg2', 'postgresql', 'mysql' a 'oracle'. Databáze PostgreSQL má dvě možnosti, přičemž 'postgresql_psycopg2' je novější verze rozhraní. Druhá konstanta, DATABASE_NAME, je absolutní cesta k souboru databáze. Nic nezkazíme, když bude soubor s databází uložen v adresáři projektu, ať je to všechno na jednom místě.

Jestliže hodláte pracovat s jiným databázovým systémem než s SQLite, konstanta DATABASE_NAME nenastavuje umístění, ale název databáze. Měli bychom pak vyplnit další konstanty, DATABASE_USER a DATABASE_PASSWORD, jež nastavují jméno a heslo databázového uživatele. Máme také možnost upravit nepovinné konstanty DATABASE_HOST a DATABASE_PORT, pomocí kterých můžeme specifikovat doménu a port v případě, že se databázový server nenachází na standardním umístění.

Po uložení konfiguračního souboru provedeme synchronizaci databáze. Tím se vytvoří základní tabulky a budeme mít možnost přidat uživatele s administrátorským oprávněním. Toho později využijeme při přihlašování do administračního rozhraní projektu, takže si přístupové údaje rozhodně zapamatujte. První synchronizace databáze vypadá nějak takto:

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

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 'dqd'):
E-mail address: id@dqd.cz
Password:
Password (again):
Superuser created successfully.
Installing index for auth.Permission model
Installing index for auth.Message model 

Pokud synchronizace proběhla úspěšně, můžeme si zkusit spustit příkazový řádek databáze (pravděpodobně bude ale nejprve potřeba nainstalovat balíček  sqlite3):

$ python manage.py dbshell
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> .tables
auth_group                  auth_user_groups
auth_group_permissions      auth_user_user_permissions
auth_message                django_content_type
auth_permission             django_session
auth_user                   django_site
sqlite> .quit 

Pomocí tohoto příkazového řádku můžeme ručně ovládat databázi, což se někdy může hodit. Každý databázový systém má ovšem trochu odlišnou syntaxi příkazů, takže pozor na to.

Aplikace videopůjčovna

Ponecháme na chvíli Django stranou, protože si teď zkusíme představit aplikaci, na které si budeme vysvětlovat databázový model. Dejme tomu, že dostanete zakázku na vytvoření webu pro síť videopůjčoven. V takové videopůjčovně nepůjčují videorekordéry, ale DVD a Blu-ray disky a také se tam dají nalézt nějaké VHS kazety.

Django video store

Protože už videopůjčovny nevynáší tolik a je krize, zadavatel se rozhodl šetřit a chce aplikaci co nejjednodušší. Bude mu stačit přehled všech poboček, katalog filmů, informace o půjčování a několik funkcí navíc pro registrované uživatele. Celé to má být ovladatelné přes administraci. Vytvořit něco takového by mělo být v Djangu bez problémů, takže se do toho můžeme rovnou pustit.

Modelujeme

Abychom mohli tvořit nezávisle od předchozích pokusů, založíme si opět novou aplikaci. Můžeme ji nazvat třeba video_store, tedy anglicky videopůjčovna. Aplikaci vytvoříme příkazem python manage.py startapp video_store a po vytvoření bychom ji měli začlenit mezi aplikace využívající databázi, které jsou zapsány v konstantě INSTALLED_APPS. Když to uděláme, Django při příští synchronizaci databáze bude hledat modely i v naší nové aplikaci. Konstantu najdeme na konci souboru settings.py a i s nově přidanou aplikací by měla vypadat nějak takto:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'hrajeme_si.video_store',
) 
Konstantu INSTALLED_APPS je potřeba aktualizovat pokaždé, když přidáme novou aplikaci, která má spolupracovat s databázi.

Vytvoření prvního modelu

V nově vytvořeném adresáři video_store si otevřeme soubor models.py. Do tohoto souboru se zadávají definice modelů, které nám určují schéma databáze. Zjednodušeně řečeno, tabulka je třída a sloupec v tabulce je atribut dané třídy. Všechny modely se odvozují od třídy Model z modulu django.db.models. Definice prvního modelu, který má znázorňovat provozovnu videopůjčovny, vypadá takhle:

from django.db import models

class Store(models.Model):
    store = models.CharField('Provozovna', max_length=100)
    address = models.CharField('Adresa', max_length=100)
    city = models.CharField('Obec', max_length=100)
    postal_code = models.CharField('PSČ', max_length=10)
    email = models.EmailField('E-mail', blank=True)
    description = models.TextField('Popis', blank=True)

    def __unicode__(self):
        return self.store

    class Meta:
        verbose_name = 'provozovna'
        verbose_name_plural = 'provozovny'
Počínaje tímto dílem si budete moci na konci článku stáhnout zdrojový kód projektu (bez souboru settings.py), takže budou z důvodů čitelnosti vypsány pouhé úryvky kódu.

Třída Store obsahuje několik atributů. První čtyři jsou pole typu CharField, což odpovídá databázovému typu VARCHAR, tedy krátkému řetězci. Tento typ potřebuje mít stanovenou maximální délku pomocí parametru max_length. Atribut email je typu EmailField a používá se pro ukládání e-mailových adres. Parametr blank nastavuje, zda může být obsah dané položky prázdný a má výchozí hodnotu False (tzn. je potřeba něco zadat). Poslední atribut je typu TextField, který je v databázi uložen jako TEXT  — tento typ se používá pro ukládání delších textů. Parametr, který stojí u všech položek na prvním místě (lze ho také zadávat jako verbose_name), slouží k pojmenování atributu a není povinný. Kdybychom ho nezadali, odvodil by se z názvu atributu. Přehled všech typů atributů je opět popsán v oficiální dokumentaci.

Takže každá pobočka bude mít přiřazený nějaký název, adresu a nepovinně e-mailovou adresu a popis. Metoda __unicode__ je unikódová verze metody __str__, která je v Pythonu používána pro textové znázornění objektu, například při ladícím výpisu. V naší definici se zobrazí název provozovny, což by mělo objekt dostatečně identifikovat. Třída také obsahuje podtřídu Meta, pomocí které se dají nastavit dodatečné vlastnosti modelu. V našem případě přenastavujeme vlastnosti verbose_name a verbose_name_plural. Ty určují název modelu v jednotném a množném čísle. To má pozdější využití v administraci.

Od modelů k databázi

Když máme správně nastavenou databázi a definovali jsme si model, můžeme si nechat vytvořit příslušnou tabulku. Název tabulky se automaticky odvodí z názvu aplikace a modelu, případně ho máme možnost nastavit přes vlastnost modelu db_table. Každopádně si nejprve ověříme, jestli naše definice modelu neobsahuje nějaké chyby:

$ python manage.py validate
0 errors found 

Evidentně je všechno v pořádku a pro zajímavost si můžeme nechat vypsat SQL kód pro vytvoření tabulky:

$ python manage.py sql video_store
BEGIN;
CREATE TABLE "video_store_store" (
    "id" integer NOT NULL PRIMARY KEY,
    "store" varchar(100) NOT NULL,
    "address" varchar(100) NOT NULL,
    "city" varchar(100) NOT NULL,
    "postal_code" varchar(10) NOT NULL,
    "email" varchar(75) NOT NULL,
    "description" text NOT NULL
);
COMMIT; 

Všimněte si hlavně primárního klíče id, který se přidává automaticky ke všem tabulkám z důvodů jednoznačné identifikace našich záznamů. A teď si konečně synchronizujeme projekt s databází:

$ python manage.py syncdb
Creating table video_store_store 

Vytvořila se nám nová tabulka, do které se budou ukládat data o pobočkách. Protože se k databázi přistupuje pomocí objektů, můžeme si jednoduše spustit interpret Pythonu a ukázat si manipulaci s daty:

$ python manage.py shell
Python 2.5.2 (r252:60911, Jan  4 2009, 21:59:32)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> 
Trojitý znak „větší než“ ( >>>) označuje interpret Pythonu. Pokaždé když bude někde uvedený, musíte mít interpret spuštěný příkazem python manage.py shell a příklady si zkoušet tam. Tento příkaz rovnou načte i nastavení projektu, takže můžeme ihned využívat přístup k databázi.

Vkládání záznamů do tabulky

Začneme importem našeho modelu a založením několika objektů poboček:

>>> from hrajeme_si.video_store.models import Store
>>> s1 = Store()
>>> s1.store = 'Videostore Praha'
>>> s1.address = 'Jana Nováka 42'
>>> s1.city = 'Praha 1'
>>> s1.postal_code = '110 00'
>>> s1.email = 'video-store-praha@example.cz'
>>> s1.description = 'Otevřeno denně od 8 do 20 hodin.'
>>> s2 = Store(store='Videostore Praha 2', address='Nepojmenovaná 8', city='Praha 2', postal_code='120 00')
>>> s3 = Store(store='Videostore Brno', address='Náměstí Svobody 1', city='Brno', postal_code='602 00') 

Vytvořili jsme si tři instance modelu Store. V prvním případě je použit prázdný konstruktor a data jsou doplněna později, v dalších dvou data předáváme přímo přes konstruktor. Oba způsoby jsou možné, druhý je preferovaný. Po vytvoření objektů můžeme jejich atributy libovolně měnit a až jsme s výsledkem spokojeni, zavoláme metodu save, která data uloží do tabulky:

>>> s1.save()
>>> s2.save()
>>> s3.save() 

Záznamům se přiřadí automaticky hodnota id podle pořadí, v jakém byly uloženy. Obsah tabulky poté vypadá takto:

id store address city postal_code email description
1 Videostore Praha 1 Jana Nováka 42 Praha 1 110 00 video-store-praha@example.cz Otevřeno denně od 8 do 20 hodin.
2 Videostore Praha 2 Nepojmenovaná 8 Praha 2 120 00
3 Videostore Brno Náměstí Svobody 1 Brno 602 00

Související odkazy

Ve čtvrtém díle budeme pokračovat v hraní si s databázovými modely.

Autor je dlouhodobým studentem Fakulty informatiky, webový nadšenec a programátor — nejraději programuje v jazycích Haskell a Python.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 3

Přehled komentářů

starenka doom
Questione Sqlite3
Pavel Dvořák Re: Sqlite3
Zdroj: https://www.zdrojak.cz/?p=3078