Na portalu Heroku.com można udostępnić całemu światu różne aplikacje, w tym te napisane w Pythonie, jak ten projekt. Wcześniej projekt był testowany na różnych środowiskach testowych: Fedora 25, Arch Linux, Windows 10. Teraz pora na Heroku.
Aby ułatwić sobie życie z rozwijaniem i wdrażaniem, utworzyłem nową gałąź „heroku”. W tej gałęzi wrzucam wszelkie zmiany w konfiguracji.
Wymagania
Przed wdrożeniem na Heroku projektu trzeba założyć konto. Założenie konta jest proste: przechodzisz przez formularz rejestracyjny, aktywujesz konto i możesz wrzucać aplikacje. Możesz też instalować dodatki, takie jak bazy danych.
Mając założone konto, trzeba było zaktualizować plik requirements.txt, utworzyć plik runtime.txt i Procfile. Plik runtime.txt zawiera nazwę i wersję środowiska Python, które będzie używane. W Procfile zawarłem polecenia do wykonania podczas wdrażania.
W pliku requirements.txt dołożyłem następujące moduły: gunicorn, whitenoise, dj-database-url, psycopg2. Wykorzystywaną bazą danych jest baza PostgreSQL, zamiast bazy SQLite, którą wykorzystuję do testów.
Wdrażanie
Wdrażanie realizuję przez integrację z Githubem. Po połączeniu z Githubem wybieram gałąź heroku i wciskam Deploy Branch. Zaczyna się proces wdrażania.
Są trzy etapy: pierwszy – pobranie kodu z gałęzi na Githubie. Drugi etap – budowa projektu (pobranie zależności, wykonanie działań konfiguracyjnych, utworzenie kontenera z aplikacją) i trzeci – udostępnienie aplikacji. Jeżeli etap drugi zakończy się powodzeniem, aplikacja będzie dostępna pod wskazanym adresem.
Co jeszcze zostaje po wdrożeniu?
Żeby aplikacja działała, potrzebne są jeszcze: utworzenie odpowiednich tabel w bazie danych. Wykorzystałem dobrze znane polecenie python manage.py migrate, ale okazało się, że to za mało. Nie było tabeli TaskList_task. Musiałem ją ręcznie utworzyć.
W SQLite polecenie do tworzenia tabeli jest takie:
CREATE TABLE IF NOT EXISTS "TaskList_task" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(256) NOT NULL, "description" text NOT NULL, "end" datetime NOT NULL, "done" bool NOT NULL, "start" datetime NOT NULL, "user_id" integer NOT NULL default 0);
Aby przystosować to polecenie do specyfiki PostgreSQL trzeba dokonać pewnych zmian: nie ma kolumny AUTOINCREMENT – trzeba zastosować SERIAL lub tak jak
w Oracle utworzyć sekwencję i pobierać kolejną wartość z sekwencji jako identyfikator zadania.
Druga rzecz: zamiana datetime na timestamp. I trzecia: zamienić bool na boolean.
Efekty zmian są takie:
CREATE TABLE IF NOT EXISTS "TaskList_task" ("id" SERIAL UNIQUE, "name" varchar(256) NOT NULL, "description" text NOT NULL, "end" TIMESTAMP NOT NULL, "done" boolean NOT NULL, "start" TIMESTAMP NOT NULL, "user_id" integer NOT NULL default 0);
Jeszcze doszły problemy z nakładaniem się ograniczenia na tabeli auth_user (tabela z użytkownikami). Polegały na rzucaniu wyjątkami o złamaniu ograniczenia na nowo tworzonym użytkowniku. Weryfikacja, czy użytkownik istnieje, już jest w aplikacji i kończy się komunikatem walidacyjnym, że taki użytkownik już istnieje.
Wystarczyło usunąć to ograniczenie. Przy okazji mała refaktoryzacja – zamiana obsługi wyjątku DoesNotExist na metodę get_or_create oraz zmiana klasy bazowej RegisterForm z CreateView na FormView.
Do czego są dodatkowe pakiety?
Pakiet gunicorn jest serwerem WWW, który można wykorzystać produkcyjnie.
Pakiet dj-database-url pozwala wyciągnąć pasującą Django konfigurację połączenia z bazą danych.
Pakiet whitenoise pozwala na udostępnianie plików statycznych (HTML, CSS, JavaScript) protokołem HTTP, jak serwer WWW, np. przez adres /static.
Pakiet psycopg2 pozwala obsłużyć PostgreSQL. Innymi słowy adapter PostgreSQL dla Pythona.
Efekt końcowy
Aplikacja działa pod adresem https://django-tasklist.herokuapp.com/.
Możecie testować ile wlezie.