Tvorba internetových aplikací

Jakub Klinkovský

:: České vysoké učení technické v Praze
:: Fakulta jaderná a fyzikálně inženýrská
:: Katedra softwarového inženýrství

Akademický rok 2023-2024

Databázové systémy

Základní pojmy

  • Databázový systém je informační systém sloužící pro ukládání dat a práci s nimi.
  • Redundance (nadbytečnost) je stav, kdy jsou tytéž údaje uložené na několika místech.
  • Nekonzistence (rozpornost) je stav, kdy je aktualizována jen část redundantních dat (nikoli všechna data).
  • Integrita (celistvost) je stav, kdy data odpovídají realitě (např. věk je kladné číslo, měsíc je číslo mezi 1 a 12).

Vývoj databázových systémů

  • vývoj od 1950
  • 1970-1980 – teorie relačního databázového modelu, vznik SQL
  • 1990-2000 – objektově orientovaný datový model
  • 2000-2010 – NoSQL (velmi rychlé a škálovatelné), NewSQL (modernizace SQL)

Systémy pro správu databází

  • anglicky database management system (DBMS)
  • samostatný program, který se stará o správu dat v databázi a přístup k nim
    (data jsou typicky reprezentovaná pomocí souboru(ů) s pevně danou strukturou)
  • umožňují oddělit aplikační vrstvu od datové (DBMS definuje rozhraní pro přístup k datům)
  • výhody:
    • omezení redundance (při správném návrhu databáze)
    • konzistence (stav bez rozporů) a integrita dat (kontrola integritních omezení)
    • sdílení dat, ochrana dat před zneužitím (omezení přístupu)
    • nezávislost dat na aplikaci, centrální správa dat
    • jednotný přístup k datům, možnost využití standardních dotazovacích jazyků (např. structured query language, SQL)

Příklady systémů pro správu databází

  • relační: MySQL, MariaDB, PostgreSQL, Microsoft SQL Server, Oracle Database
  • sloupcové: CrateDB, Kudu, InfluxDB, Prometheus (ukládání časových řad)
  • objektové: OpenAccess, ODABA, Wakanda
  • dokumentové: Apache CouchDB, MongoDB, Oracle NoSQL Database
  • in-memory: Memcached, Redis

Relační databázový model

Je založen na principu tabulek a vztahů mezi nimi.

  • tabulka (entita, relace) se skládá z hlavičky a těla (stupeň relace = počet sloupců, kardinalita = počet řádků)
  • atribut = sloupec tabulky (doména = datový typ)
  • záznam (n-tice) = řádek tabulky
  • klíč = množina atributů tabulky, které jsou podstatné pro definici integritních omezení
  • vztah (relationship) = propojení mezi tabulkami

Typy klíčů a vztahů

  • klíče: primární (PK), unikátní (UK), cizí (FK)
  • vztah je odkaz mezi hodnotami cizího klíče (tab. 1) a primárního klíče (tab. 2)
  • typy vztahů: one-to-many (neunikátní FK na unikátní PK), one-to-one (PK je současně FK), many-to-many (normalizace pomocí dodatečné tabulky)

contain center

Integritní omezení

  • doménová integrita – kontrola datového typu hodnot v záznamu (dle typu sloupce)
    • NOT NULL integrita
    • některé DBMS umožňují specifikovat dodatečné kontroly (např. PostgreSQL)
  • entitní integrita – dána hodnotou primárního klíče (musí být unikátní)
  • referenční integrita – dána hodnotou cizího klíče (musí existovat odpovídající záznam v odkazované tabulce)
  • integrita daná unikátním klíčem – hodnoty v dané tabulce musí být unikátní (ale mohou být NULL)

Poznámka: některé DBMS jsou nechvalně proslulé ignorováním integritních omezení (např. MySQL, MariaDB)

Normalizace dat

Normalizace = postupná transformace tabulky do vhodnějšího tvaru (pomocí bezeztrátové dekompozice).

Cíle normalizace:

  • vytvořit flexibilní návrh databáze
  • správně umístit atributy do tabulek
  • správně definovat primární klíč každé tabulky
  • snížit (odstranit) redundanci dat
  • maximalizovat stabilitu datové struktury
  • zvýšit efektivitu programování aplikací využívajících databázi
  • snížit náklady na údržbu

Normální formy schémat relací

  • 0NF (non-first normal form): tabulka obsahuje nějaké pole, kde je více hodnot.
  • 1NF: tabulka má primární klíč a atributy tabulky jsou atomické (dále nedělitelné).
  • 2NF: platí vše z 1NF + neexistuje závislost na části klíče (žádný neklíčový atribut není parciálně funkčně závislý na klíčovém).
  • 3NF: platí vše z 2NF + neexistuje „mimoklíčová závislost“ (žádný neklíčový atribut není tranzitivně závislý na klíči). Poznámka: pro složené klíče se zkoumá také BCNF (Boyceova–Coddova normální forma).
  • 4NF: platí vše z 3NF + „tabulka popisuje jedno jsoucno“ (je-li neklíčový atribut netriviálně závislý, pak musí být závislý pouze na klíčovém).
  • 5NF: tabulka je ve 4NF + přidání nového podstatného (důležitého a „rozumného“) sloupce nezpůsobí pád tabulky do nižší formy (většinou do 2NF).

Požadavky na návrh

Požadavky na návrh schématu databáze pomocí normalizace:

  • bezeztrátovost dekompozice (spojením dekomponovaných tabulek musí vzniknout přesně původní tabulka)
  • zachování závislostí
  • dosažení minimálně 3NF

Poznámka: některé postupy používané v praxi úmyslně provádí denormalizaci kvůli rychlejší odezvě DBMS na dotazy (což je ale technický problém, který by se měl řešit vhodnější implementací).

Návrh schématu databáze

Návrh schématu databáze má 3 úrovně:

  1. konceptuální úroveň – cílem je vytvořit sémantický model popisované reality
    (návrh ERA (entity-relationship-attribute) modelu např. pomocí creately.com
  2. logická úroveň – pohledy na data vytvořené nad modelem popisované reality
    (výběr požadovaných dat z kombinace tabulek)
  3. implementační úroveň – výběr DBMS, ve kterém bude databáze vytvořena
    (a samotné vytvoření)

Příklad 1

Lidé a jejich vlastnosti (dekompozice vztahu M:N)

contain center

Příklad 2

Kategorie, zboží v nich a vývoj cen

contain center

Příklad 3

Kategorie a zboží v nich (dekompozice vztahu M:N)

contain center

Jazyk SQL pro relační databázové systémy

Jazyk SQL

SQL (structured query language) = strukturovaný dotazovací jazyk

  • Je používán ve většině relačních databázových systémech.
  • V současnosti není SQL jen dotazovacím jazykem (DQL, data query language), ale obsahuje i další prostředky:
    • DDL (data definition language) – jazyk pro definici dat (např. CREATE, DROP)
    • DCL (data control language) – jazyk pro řízení dat (např. GRANT, REVOKE)
    • DML (data manipulation language) – jazyk pro manipulaci s daty (např. INSERT, UPDATE)
  • Existují normy jazyka SQL schválené organizací ANSI, ale většina relačních DBMS implementuje jen určitou část normy + vlastní funkce ⇒ problémy s přenositelností kódu SQL na jiný DBMS.

Příklad – vytvoření tabulky

CREATE TABLE [ IF NOT EXISTS ] table_name
(
  { column_name data_type [ constraints ... ] }
  [, ... ]
)
[ modifiers ... ];

kde constraints může být např.:

{ NOT NULL |
  NULL |
  CHECK ( expression ) |
  DEFAULT default_expr |
  UNIQUE index_parameters |
  PRIMARY KEY index_parameters |
  FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ modifiers ... ] }

Legenda: [ text ] – optional part, ... – opakování elementu

Příklad – změna struktury tabulky

ALTER TABLE [ IF EXISTS ] table_name action [, ...];

kde action může být např. ADD, MODIFY, DROP atd. s příslušnými parametry.

Pomocí příkazu ALTER TABLE lze např.:

  • přidat nový atribut (sloupec)
  • změnit definici atributu (za určitých podmínek)
  • odebrat atribut
  • přidat, změnit či odebrat cizí klíč
  • přidat či odebrat podmínku mezi sloupci

Příklad – odstranění tabulky

DROP TABLE table_name;

Pozor: pomocí příkazu DROP TABLE odstraníte tabulku včetně jejích dat!

Tabulku nelze odstranit, pokud by došlo k porušení integrity databáze, např.:

  • na tabulku odkazují cizí klíče z jiných tabulek (došlo by k porušení referenční integrity databáze)
  • tabulka je součástí nějakého pohledu (VIEW) nebo procedury (PROCEDURE)

Příklad – vložení záznamu do tabulky

INSERT INTO table_name [ ( column_name [, ...] ) ]
VALUES ( { expression | DEFAULT } [, ...] ) [, ...]
[ modifiers ... ];

Pomocí příkazu INSERT lze vložit jeden záznam do zadané tabulky (v některých DBMS lze vložit více záznamů najednou).

Nelze vložit data, která porušují integritní omezení dané databáze (např. doménová, entitní nebo referenční integrita).

Příklad – změna záznamů v tabulce

UPDATE table_name [ modifiers ... ]
SET { column_name = { expression | DEFAULT } } [, ...]
[ WHERE condition ]
[ modifiers ... ];

Pomocí příkazu UPDATE lze změnit jednu nebo více hodnot u jednoho či více záznamů. Počet ovlivněných záznamů se určí podle podmínky WHERE – při absenci WHERE se změna provede u všech záznamů v tabulce!

Upravené záznamy musí splňovat integritní omezení dané databáze (např. doménová, entitní nebo referenční integrita), jinak příkaz skončí chybou.

Při změně primárního klíče provede DBMS příslušné akce v podřízených tabulkách (mají-li ON UPDATE CASCADE).

Příklad – smazání záznamů v tabulce

DELETE FROM table_name [ modifiers ... ]
[ WHERE condition ];

Pomocí příkazu DELETE lze smazat jeden nebo více záznamů z uvedené tabulky. Počet smazaných záznamů se určí podle podmínky WHERE – při absenci WHERE se vymažou všechny záznamy z tabulky!

Smazáním záznamů nesmí dojít k porušení referenční integrity dané databáze, jinak příkaz skončí chybou.

Cizí klíče v podřízených tabulkách mohou být upraveny pomocí definovaných akcí (např. ON DELETE CASCADE nebo ON DELETE SET NULL).

Příklad – výběr dat z tabulky

SELECT <projection>
FROM <data_source>
[ WHERE <restriction> ]
[ GROUP BY <aggregation> [ HAVING <second_restriction> ] ]
[ ORDER BY <ordering> ];

Vykonávání dotazu se provádí v následujícím pořadí:

  1. zdroj datrestrikce
  2. agregace
  3. druhá restrikce
  4. setřídění
  5. projekcevýstup

Výsledkem je "virtuální tabulka", kterou lze použít jako zdroj dat v dalších dotazech.

Operace při výběru dat z tabulky I

  • Projekce:
    • názvy sloupců z uvedených zdrojů dat (jsou-li použity alespoň dva zdroje dat a zároveň ve dvou je stejný název sloupce, musíme jeho název uvést ve tvaru <tabulka>.<sloupec>)
    • pro výběr všech sloupců slouží *
    • lze použít i funkce, např. SUM(<sloupec>)
    • lze přejmenovat/pojmenovat sloupec výsledku:
      <sloupec nebo výraz> AS <nové_jméno>
  • Zdroj dat = fyzická nebo virtuální tabulka, případně spojení více tabulek (JOIN). Tabulku lze přejmenovat (např. při spojení tabulky se sebou samou). Vizte dále.
  • Restrikce pomocí podmínka (logický výraz)
    • Určuje, které záznamy budou vybrány (ty, pro něž je podmínka platná, TRUE).

Operace při výběru dat z tabulky II

  • Agregace = výraz (většinou jen název sloupce, resp. sloupců), podle kterých se seskupí řádky tabulky do množin. Vizte dále.
  • Seřazení = výraz (typicky název sloupce, resp. sloupců), podle kterého se mají seřadit řádky výsledku.
    • Lze použít sloupce existující ve zdroji dat (nemusí být částí projekce). První výraz je hlavním kritériem řazení, ostatní jsou chápány jako sekundární.
    • Implicitní je vzestupné řazení (ASC), pro sestupné je nutno doplnit DESC.

Zdroj dat v dotazu

Zdrojem dat v dotazu může být:

  1. jedna (konkrétní) tabulka, např.
    SELECT * FROM skola ORDER BY nazev;
    
    ⇒ výpis všech dat z tabulky SKOLA, řazeno dle názvu
  2. více tabulek (kartézský součin nebo spojení tabulek dle vztahů), např.
    SELECT jmeno, prijmeni
    FROM student JOIN studium ON idst=kdo
    WHERE kde = 1
    ORDER BY prijmeni, jmeno;
    
    ⇒ výpis jména a příjmení studentů, kteří studují na škole s identifikátorem kde=1 (řazeno dle příjmení, dále dle jména)

Zdroj dat – kartézský součin

Tabulky v databázi lze spojovat, abychom získali potřebná data. Možnosti:

  1. Kartézský součin (CROSS JOIN)
    • syntaxe: tabA, tabB
    • výsledek: spojí řádky obou tabulek „každý s každým“ (pokud tabAm sloupců a M řádků a tabBn sloupců a N řádků, tak výsledný kartézský součin obsahuje m + n sloupců a M · N řádků)
    • používat jen se správnou podmínkou WHERE!!!

center

Zdroj dat – vnitřní spojení

  1. Vnitřní spojení (INNER JOIN)
    • syntaxe: tabA JOIN tabB ON <podmínka>
    • výsledek: spojí řádky obou tabulek na základě podmínky (typicky „cizí klíč=příslušnému primárnímu“)
    • DBMS jsou na JOIN optimalizované ⇒ je rychlejší než kartézský součin

center

Zdroj dat – levé a pravé vnější spojení

  1. Levé (vnější) spojení (LEFT JOIN)
    • syntaxe: tabA LEFT JOIN tabB ON <podmínka>
    • výsledek: spojí tabulku tabA s tabulkou tabB tak, že zachová i ty řádky z tabA, které nemají ekvivalent v tabB
    • záleží na pořadí tabulek!
    • je pomalejší než vnitřní spojení

center

  1. Pravé (vnější) spojení (RIGHT JOIN): tabA RIGHT JOIN tabB ON <podm>
    výsledek je (až na pořadí atributů) shodný s tabB LEFT JOIN tabA ON <podm>

Zdroj dat – úplné vnější spojení

  1. Úplné vnější spojení (FULL JOIN)
    • syntaxe: tabA FULL [OUTER] JOIN tabB ON <podmínka>
    • výsledek: spojí tabA s tabulkou tabB tak, že zachová jak řádky z tabA, tak řádky z tabB, které nemají ekvivalent v druhé tabulce
    • v praxi se moc nepoužívá, některé DBMS ho nepodporují

center

Agregace – seskupování řádků

Klauzule GROUP BY slouží k seskupení řádků do množin. Na vzniklé množiny se pak aplikují tzv. agregační funkce, nejčastěji to jsou:

funkce výsledek p (typicky název sloupce nebo výraz)
COUNT(*) počet záznamů v daném zdroji dat
COUNT(<p>) počet neNULL hodnot libovolné
SUM(<p>) součet hodnot p číslo
MIN(<p>) minimum z hodnot p číslo, řetězec, datum
MAX(<p>) maximum z hodnot p číslo, řetězec, datum
AVG(<p>) aritmetický průměr číslo

Ukázky dotazů

Výpis jména a příjmení studentů, jejichž příjmení začíná 'Nov', řazeno dle příjmení, dále dle jména:

SELECT jmeno, prijmeni FROM student
WHERE prijmeni LIKE 'Nov%' ORDER BY prijmeni, jmeno;

Výpis ID studentů (kdo), kteří aktuálně studují na škole, jejíž idsk=3 (pořadí je náhodné):

SELECT kdo FROM studium
WHERE kde=3 AND do_kdy IS NULL;

Výpis studentů s počtem škol, které někdy studovali (resp. studují), neřazeno:

SELECT idst, MIN(prijmeni) AS prijm, COUNT(kde) AS pocet_skol
FROM student LEFT JOIN studium ON idst=kdo
GROUP BY idst;

Databázové systémy ve frameworku Django

Backend pro databázový systém

  • Django podporuje tyto databázové systémy: PostgreSQL, MariaDB, MySQL, Oracle, SQLite.
  • Výchozí backend je SQLite – jednoduchý databázový systém implementovaný v C, nevyžaduje instalaci externí aplikace, databáze realizována v jednom souboru (viz db.sqlite3 v našem projektu).
  • SQLite databázi lze ručně editovat pomocí programu SQLite Browser.
  • Alternativní databázový systém lze v projektu nastavit v souboru settings.py, viz dokumentace.

Objektově relační mapování (ORM)

Systém ORM poskytuje automatickou konverzi a synchronizaci dat mezi relační databází a objektově-orientovaným programovacím jazykem.

Terminologie a implementace ve frameworku Django (viz dokumentace):

  • model = objekt reprezentující konkrétní záznam v databázi (potomek třídy django.db.models.Model)
  • field = popis atributů modelu (atribut objektu odpovídá sloupci tabulky v relačním modelu)
    • typ – určuje datový typ v databázi a automaticky generovaných formulářích
    • parametry – např. null, blank, choices, default, help_text, primary_key, unique

Definice vlastních modelů probíhá v souboru models.py.

Příklad – ORM pro jednoduchý model

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

Django vytvoří následující tabulku pomocí SQL:

CREATE TABLE myapp_person (
    "id" bigint NOT NULL PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);
  • název tabulky je prefixovaný názvem aplikace (myapp)
  • sloupec id byl přidán automaticky (lze zakázat)
  • Django generuje SQL v dialektu pro daný DBMS (v tomto příkladu PostgreSQL)

Definice vazeb mezi modely

Vazby mezi modely lze definovat pomocí třídy (field) ForeignKey:

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

Dále třídy ManyToManyField a OneToOneField.

Dostupné typy atributů (fields)

Kompletní přehled viz dokumentace.

  • BooleanField, IntegerField, BigIntegerField, FloatField, DecimalField
  • PositiveIntegerField, PositiveBigIntegerField
  • CharField (parametr max_length), TextField (neomezená velikost)
  • DateField, TimeField, DateTimeField, DurationField (v Pythonu objekty datetime.date, datetime.time, datetime.datetime, datetime.timedelta)
  • další: EmailField, URLField, UUIDField, JSONField, ImageField, FileField, FilePathField, ...

Omezení při definici modelů

  1. Název atributu nesmí být klíčové slovo v jazyku Python:
    class Example(models.Model):
        pass = models.IntegerField()    # 'pass' je klíčové slovo!
    
  2. Název atributu nesmí obsahovat 2 nebo více podtržítek za sebou:
    class Example(models.Model):
        foo__bar = models.IntegerField() # 'foo__bar' má dvě podtržítka!
    
    Dvojice podtržítek (__) má speciální význam v syntaxi pro dotazy, viz později.
  3. Název atributu nesmí končit podtržítkem (z podobných důvodů).

Správa databáze pomocí skriptu manage.py

Skript manage.py poskytuje několik podpříkazů pro správu databáze projektu:

  • dbshell – spustí příkazového klienta pro danou databázi
  • makemigrations – vytvoří soubory pro změnu (migraci) databáze po změně specifikace modelů – viz dokumentace procesu migrace
    • soubory jsou v adresářích <app>/migrations/, např. pokus/migrations/
  • showmigrations – zobrazí stav migrací v projektu
  • migrate – synchronizuje stav databáze s množinou migrací
  • loaddata – vyhledá data pro inicializaci a vloží je do databáze
  • dumpdata – vypíše všechna data v databázi
  • inspectdb – vytvoří objektový model (v syntaxi Pythonu) pro existující databázi

ORM workflow

Vývoj nové aplikace (resp. nového modelu):

  1. Definice modelů v souboru models.py (viz předchozí slajdy)
  2. Vytvoření odpovídajících tabulek v databázi pomocí skriptu manage.py
    • vytvoření tzv. migrace – soubor popisující změny, které je třeba provést
    • provedení migrací (je možné řetězit a aplikovat na různé databáze)
  3. Spuštění aplikace (web serveru)
  4. Dále se ORM stará o obsah jednotlivých tabulek (vytváření nových objektů a vkládání do databáze, dotazy na existující objekty a případná aktualizace atributů v databázi)

Komplikace: změna schématu existující databáze, pokud nechceme přijít o data.

Dokončení instalace interních aplikací v Django projektu

Po vytvoření projektu máme neprovedené migrace pro aplikace admin, auth, atd.:

> python manage.py showmigrations 
admin
 [ ] 0001_initial
 [ ] 0002_logentry_remove_auto_add
 [ ] 0003_logentry_add_action_flag_choices
auth
 [ ] 0001_initial
 [ ] 0002_alter_permission_name_max_length
 [ ] 0003_alter_user_email_max_length
 [ ] 0004_alter_user_username_opts
 [ ] 0005_alter_user_last_login_null
 [ ] 0006_require_contenttypes_0002
 [ ] 0007_alter_validators_add_error_messages
 [ ] 0008_alter_user_username_max_length
 [ ] 0009_alter_user_last_name_max_length
 [ ] 0010_alter_group_name_max_length
 [ ] 0011_update_proxy_permissions
 [ ] 0012_alter_user_first_name_max_length
contenttypes
 [ ] 0001_initial
 [ ] 0002_remove_content_type_name
pokus
 (no migrations)
sessions
 [ ] 0001_initial

Provedení migrace databáze

> python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Ověření stavu migrací

> python manage.py showmigrations 
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
 [X] 0003_logentry_add_action_flag_choices
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
 [X] 0008_alter_user_username_max_length
 [X] 0009_alter_user_last_name_max_length
 [X] 0010_alter_group_name_max_length
 [X] 0011_update_proxy_permissions
 [X] 0012_alter_user_first_name_max_length
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
pokus
 (no migrations)
sessions
 [X] 0001_initial

Přidání modelů

  1. Vytvoříme nové modely (např. ze slajdu 39)
  2. Vytvoříme migraci:
    > python manage.py makemigrations 
    Migrations for 'pokus':
      pokus/migrations/0001_initial.py
        - Create model Musician
        - Create model Album
    
  3. Provedeme migrace:
    > python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, pokus, sessions
    Running migrations:
      Applying pokus.0001_initial... OK
    

Vložení záznamů do databáze – admin webUI

Pro vývoj aplikace můžeme ručně vložit testovací data:

  1. Pomocí administrátorské aplikace – viz http://localhost:8000/admin
    • nejdřív je potřeba vytvořit administrátorský účet pomocí příkazu
      python manage.py createsuperuser
    • modely je potřeba registrovat v souboru admin.py, aby se zde zobrazily:
      from .models import Musician, Album
      admin.site.register(Musician)
      admin.site.register(Album)
      

Vložení záznamů do databáze – shell

  1. Pomocí interaktivního shellu: python manage.py shell, např.:
    >>> from pokus.models import *
    
    >>> karel = Musician()
    >>> karel.first_name = "Karel"
    >>> karel.last_name = "Gott"
    >>> karel.instrument = "zpěv"
    >>> karel.save()
    
    >>> album = Album()
    >>> album.artist = karel   # ve skutečnosti v databázi uloží pouze id
    >>> album.name = "Karel Gott"
    >>> album.release_date = "1973-01-01"
    >>> album.num_stars = 5
    >>> album.save()
    

Získání záznamů z databáze

Třída Model má speciální atribut objects pro správu přístupu k instancím:

>>> from pokus.models import *

>>> Album.objects.first()     # vrátí první objekt
>>> Album.objects.last()      # vrátí poslední objekt

>>> Album.objects.all()       # vrátí množinu všech objektů
>>> Album.objects.all()[:5]   # vrátí prvních 5 objektů

>>> Album.objects.filter(name="Karel Gott")    # filtrování dle názvu alba
>>> Album.objects.filter(artist__first_name="Karel", artist__last_name="Gott")
                            # filtrování přes vztah mezi tabulkami, spojení: '__'

>>> Album.objects.exclude(name="Karel Gott")   # doplňkové filtrování

Další možnosti: viz přístup k objektům

Testovací data pro vývoj databáze

Při vývoji aplikace není potřeba se vždy zabývat vytvářením správné migrace a někdy je lepší začít tzv. od začátku (resp. posledního funkčního stavu, který je např. nasazen na veřejném serveru).

Workflow s restartem:

  • smazat databázi (soubor db.sqlite3)
  • vytvořit databázi v počátečním stavu (dle stavu souboru models.py)
    • python manage.py makemigrations
    • python manage.py migrate
  • inicializovat databázi testovacími daty – tzv. fixtures
  • pracovat na úpravách modelů

Vložení záznamů do databáze – fixtures

  1. Adresář pokus/fixtures/ obsahuje testovací data pro aplikaci pokus:

    • několik souborů, které je třeba nahrát ve správném pořadí dle závislostí, např. python manage.py loaddata genres musicians bands albums

    • formát souborů: viz dokumentace Django

    • definice dat pro ManyToManyField: seznam hodnot PK, na která se odkazuje:

      {
          "model": "pokus.Band",
          "pk": 1,
          "fields": {
              "name": "The Beatles",
              "members": [2, 3, 4, 5]
          }
      },
      

![bg contain right:45%](images/Relational_model_concepts.png)

![w:800](images/SQL_CREATE_TABLE.png)

![w:700](images/SQL_ALTER_TABLE.png)

![w:500](images/SQL_DROP_TABLE.png)

![w:700](images/SQL_INSERT.png)

![w:800](images/SQL_UPDATE.png)

![w:500](images/SQL_DELETE.png)

![w:800](images/SQL_SELECT.png)

--- ## ERA diagram pro předchozí příklad ![w:800](images/studium_ERA.png)