Wprowadzenie.
W poprzednim wpisie stworzyliśmy pierwszy projekt oraz utworzyliśmy pierwsze podstawowe widoki. W tej części natomiast przedstawiłem krok po kroku w jaki sposób utworzyć modele w aplikacji Django oraz jak model powiązany jest z danymi w bazie danych.
Zakres artykułu.
- Tworzenie aplikacji Django – baza danych
- Tworzenie aplikacji Django – modele
Tworzenie aplikacji Django - baza danych
Dla przypomienia przedstawiłem poniżej jak wygląda struktura utworzonego poprzednio projektu.
Przed przystąpieniem do tworzenia modeli w pierwszym kroku musimy zająć się bazą danych. Gdy instalowaliśmy Django zainstalowała się z nim baza danych SQLite, która na potrzeby tego poradnika w zupełności nam wystarczy. Jak zainstalować inną bazę danych i jak dokonać konfiguracji przedstawię w innym wpisanie.
W pierwszym kroku w pliku settings.py, który znajduje się w lokalizacji myFirstApp/myFirstApp/settings.py ustawiamy sekcję unarodowienia i lokalizacji. W moim przypadku sekcja wygląda następująco.
LANGUAGE_CODE = 'pl-PL' TIME_ZONE = 'Europe/Warsaw' USE_I18N = True USE_L10N = True USE_TZ = True
Celem powyższej modyfikacji jest określenie, które części aplikacji powinny być przetłumaczone i przeformatowane do preferencji lokalnego języka lub preferencji danego użytkownika.
Kolejnym krokiem jest stworzenie tabel w bazie danych dla naszych aplikacji. Tworzenie tabel realizowane jest poprzez polecenie python3 manage.py migrate. W tej chwili możemy się zastanawiać jakie tabele stworzy ta komenda. Odpowiedź na to pytanie znajduje się po części w pliku setting.py w sekcji defioniowania aplikacji.
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
W tej chwili widzimy jedynie aplikacje, które są domyśle dodane przez Django w trakcje tworzenia projektu. W tej sekcji będziemy dodawać własne aplikacji, które mogą być swobodnie pakowane i przenoszone pomiędzy różnymi projektami. Polecenie migrate utworzy tabele dla każdej aplikacji, która znajduje się w liście INSTALLED_APPS. Po wykonaniu polecenia migrate powinniśmy otrzymać następujący efekt.
Tworzenie aplikacji Django - modele
W pierwszej kolejności wyjaśnijmy co to jest model i do czego służy. Model można powiedzieć, że jest to layout naszej bazy danych, gdzie zamieszczamy takie informacje jak: nazwy tabel, nazwy i konfigurację kolumn oraz relację między tabelami w celu uniknięcia redundancji danych.
W celu zilustrowania jak wyglądają modele załóżmy, że chcemy stworzyć stronę, gdzie będziemy zamieszczać nasze recenzję obejrzanych filmów.
W tym celu otwieramy plik models.py, który znajduje się w lokalizacji myProject/myFirstApp/models.py, a następnie musimy napisać kilka linijek kodu.
from django.db import models # Create your models here. class MovieGenres(models.Model): genre = models.CharField(max_length=128) class MovieActors(models.Model): first_name = models.CharField(max_length=64) last_name = models.CharField(max_length=64) age = models.IntegerField(default=0) class WatchedMovies(models.Model): RATES = ( ('1', 'Okropny'), ('2', 'Słaby'), ('3', 'Średni'), ('4', 'Dobry'), ('5', 'Znakomity'), ) title = models.CharField(max_length=128) release_date = models.DateTimeField('data premiery') stars = models.ManyToManyField(MovieActors) genre = models.ForeignKey(MovieGenres, on_delete=models.CASCADE) rate = models.CharField(max_length=1, choices=RATES) review = models.TextField(blank=True)
W pliku utworzyliśmy 3 modele, poprzez stworzenie 3 klas, które dziedziczą po klasie django.db.models.Model. W klasach tworzymy tak zwane pola (ang. Fields). Pole jest instancją klasy abstakcyjnej Field, która reprezentuje kolumny w tabeli. Pola są przez Django wykorzystywane do tworzenia tabel i mapowania zmiennych z danymi z bazy danych i odwrotnie. Do części klas Field podaje się argumenty, które są konieczne do podania oraz występują argumenty, które są opcjonalne. Pola mogą też być instancją klasy, która pełni funkcję relacji. Realcje wspierane przez Django to wiele do jednego, wiele do wielu oraz jeden do jednego.
W celu dodania aplikacji do projektu otwieramy plik settings.py i w sekcji definiowania aplikacji dodajemy do listy INSTALLED_APPS naszą aplikacją wpisując ‘myFirstApp.apps.MyfirstappConfig’. Klasa MyfirstappConfig znajduje się w pliku apps.py w lokalizacji myProject/myFirstApp/apps.py.
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # my apps 'myFirstApp.apps.MyfirstappConfig', ]
Od tej pory Django jest przygotowany, aby dodać aplikację do projektu. Wpisując polecenie python3 manage.py makemigrations myFirstApp sygnalizujemy, że wprowadziliśmy zmiany w modelach i w efekcie powinniśmy zobaczyć następujący komunikat.
W pliku 0001_initial.py znajduje się przygotowana konfiguracja do wprowadzenia zmian. Plik ten znajduje się w lokalizacji myProject/myFirstApp/migrations/0001_initial.py i może być przez nas modyfikowany według uznania. Dodatkowo poleceniem python3 manage.py sqlmigrate myFirstApp 0001 możemy sprawdzić jakie polecenia SQLa zostaną wykonane po przeprowadzeniu migracji. W moim przypadku wynik wygląda następująco.
BEGIN; -- -- Create model MovieActors -- CREATE TABLE "myFirstApp_movieactors" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "first_name" varchar(64) NOT NULL, "last_name" varchar(64) NOT NULL, "age" integer NOT NULL); -- -- Create model MovieGenres -- CREATE TABLE "myFirstApp_moviegenres" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "genre" varchar(128) NOT NULL); -- -- Create model WatchedMovies -- CREATE TABLE "myFirstApp_watchedmovies" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(128) NOT NULL, "release_date" datetime NOT NULL, "rate" varchar(1) NOT NULL, "review" text NOT NULL, "genre_id" integer NOT NULL REFERENCES "myFirstApp_moviegenres" ("id") DEFERRABLE INITIALLY DEFERRED); CREATE TABLE "myFirstApp_watchedmovies_stars" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "watchedmovies_id" integer NOT NULL REFERENCES "myFirstApp_watchedmovies" ("id") DEFERRABLE INITIALLY DEFERRED, "movieactors_id" integer NOT NULL REFERENCES "myFirstApp_movieactors" ("id") DEFERRABLE INITIALLY DEFERRED); CREATE INDEX "myFirstApp_watchedmovies_genre_id_bb106972" ON "myFirstApp_watchedmovies" ("genre_id"); CREATE UNIQUE INDEX "myFirstApp_watchedmovies_stars_watchedmovies_id_movieactors_id_4157b6a2_uniq" ON "myFirstApp_watchedmovies_stars" ("watchedmovies_id", "movieactors_id"); CREATE INDEX "myFirstApp_watchedmovies_stars_watchedmovies_id_d43bdce5" ON "myFirstApp_watchedmovies_stars" ("watchedmovies_id"); CREATE INDEX "myFirstApp_watchedmovies_stars_movieactors_id_2bc3ef57" ON "myFirstApp_watchedmovies_stars" ("movieactors_id"); COMMIT;
Kolejnym krokiem jest wykonanie migracji poleceniem, które już znamy to znaczy python3 manage.py migrate. Efekt jaki powinniśmy otrzymać wygląda następująco.
Bardzo ważną zaletą migracji jest to, że wykonanie migracji po dokonaniu zmian w modelach nie powoduje utraty danych. Podczas tego procesu nie są usuwane ani bazy danych, ani tabele, a jedynie dokonywana jest ich aktualizacja.