/ DevOps

DevOps statickej stránky - Premena na dynamický web cez Django

Modelová situácia:
Statická webstránka firmy, bez jediného riadku backendového kódu.
Cieľ:
Rozbehať Google Analytics a pridať novú položku do menu

Cieľ

Stránku som písal ešte pred pár rokmi. Mala byť na jednoduchú prezentáciu firmy a do dnešného dňa to všetko stačilo. Firma však získala eurofondy a na stránku bolo treba pridať banner o tom, že na novú technológiu výroby prispela EU.
Po dlhšom uvažovaní najlepšieho dizjanu som sa rozhodol spraviť to cez ďalší item v Menu. To zo sebou však prináša nudné editovanie niekoľkých HTML kódov s možnosťou chybovosti. A následne znovu editovanie po uplynutí povinnej doby zverejnenia.

Riešenie

Rozhodol som sa použiť Django. Je to síce ako na vrabca kanón, ale na rozdiel od Flasku s ním mám väčšie skúsenosti. Prečo Python a nie PHP? Pretože mám s ním väčšie skúsenosti a PHP bez frameworku je samovražda.

Architektúra

Stránka beží na osobnom VPSku na ktorom prevádzkujem ešte niekoľko ďalších stránok, vrátane tohto blogu. Rozhodol som sa pre to nemeniť existujúcu architektúru na VPS a prispôsobiť sa. Na serveri, na porte 80 mi počúva nginx server, ktorý slúži ako proxy a na základe server_name smeruje requesty na želaný docker kontajner, bežiaci lokálne na porte > 1024. Prvých 1023 portov je totiž registrovaných na špecifické služby (80 - HTTP, 443 - SSL/TLS, 22 - SSH, atď), zatiaľ čo porty 1024 - 65535 sú voľné k použitiu.

Úprava statickej stránky na dynamickú

Najskôr si vytvoríme projekt:

django-admin startproject nazovprojektu

Django je modulárny framework a dosahuje toho tým, že každá časť projektu je plne funkčnou aplikáciou, ktorú je možné odtrániť alebo znovupoužiť v inom projekte. Cez manage.py si teda vytvoríme novú (a zároveň jedinú) aplikáciu pre stránku:

python manage.py createapp nazovaplikacie

Následne vo views.py definujeme nové classy. Čo nový link, to nová trieda. Ako argument triedy sa použije trieda TemplateView. Výsledný obsah súboru nazovaplikacie/views.py je približne nasledovný:

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
from django.views.generic import TemplateView


class Index(TemplateView):
    template_name = 'index.html'

class GoogleSiteVerification(TemplateView):
    template_name = 'google46f9c98a1c857ddf.html'

class Kontakt(TemplateView):
    template_name = "kontakt.html"

class Produkty(TemplateView):
    template_name = "produkty.html"

class ProduktySladke(TemplateView):
    template_name = "produkty_sladke.html"

class ProduktySlane(TemplateView):
    template_name = "produkty_slane.html"

Ako vidieť na zdrojovom kóde, definovali sme si zároveň aj už meno template-u (šablóny). Ten však zatiaľ neexistuje, preto ho vytvoríme. V adresári projektu vytvoríme (ak ešte neexistuje) priečinok s názvom templates/ a do neho budeme ukladať novo vytvorené šablóny. Poďme začať s index.html.
Vytvoríme si súbori templates/index.html a templates/scaffold.html. Scaffold (kostra), obsahuje všetku tú omáčku rovnakú pre každú stránku, ako je dizajn panelov, umiestnenie a obsah menu, pätička a pod. Na mieste, kde by bol obsah, sa však nachádza len:

    .
    .
    .
        <!-- /.container -->
    </nav>
    
    {{ content }}

    <!-- jQuery -->
    <script src="js/jquery.js"></script>
    .
    .
    .

Čo je dôležité je: {{ content }}. Týmto riadkom sa určuje že na mieste bude nejaký blok kódu. V našom prípad je definovaný v index.html:

{% include 'scaffold.html' %}

{% block content %}
<p>Hello world</p>
{% endblock %}

{% include 'scaffold.html' %} hovorí aby sa načítal scaffold.html, {% block content %} hovorí že obsah bloku content je definovaný na nasledujúcich riadkoch.

Keby sme sa teraz však rozhodli stránku spustiť, k webstránke sa nedostaneme. Potrebujeme ešte nastaviť smerovanie v rámci aplikácie. Otvoríme teda súbor nazovprojektu/urls.py a upravíme ho, aby obsahoval nasledujúci záznam:

urlpatterns = [
    path('', include('nazovaplikacie.urls')),
]

Je možné, že urlpatterns bude obsahovať ešte aj záznam pre url admin/. Ten môžete prepísať, alebo odstrániť. Pre nás je nepotrebný. Teraz v našej aplikácii vytvoríme súbor urls.py (nazovaplikacie/urls.py).

from django.urls import path

from . import views

urlpatterns = [
    path('', views.Index.as_view(), name='index'),
    path('google46f9c98a1c857ddf.html', views.GoogleSiteVerification.as_view() ,name='google_site_verification'),
    path('kontakt', views.Kontakt.as_view(), name = "kontakt"),
    path('produkty', views.Produkty.as_view(), name = "produkty"),
    path('produkty_sladke', views.ProduktySladke.as_view(), name = "produkty_sladke"),
    path('produkty_slane', views.ProduktySlane.as_view(), name = "produkty_slane"),
]

Tým sme prepojili vyšie vytvorené triedy so šablonami a namapovali ich na url adresy typu: nazovdomeny.sk/kontakt. Pokiaľ je prvý argument metódy path prázny, berie sa to za nazovdomeny.sk/.

Teraz môžeme webstránku spustiť cez:

python manage.py runserver

Je tu však jeden problém, nenastavili sme ešte cesty pre statický obsah (CSS, JS, obrázky). Vytvoríme v adresári projektu súbor static/. Otvoríme súbor nazovprojektu/settings.py a na koniec súboru pridáme:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
    ]

Teraz znovu otvoríme šablóny, a spravíme nasledujúcu zmenu:

<script src="js/jquery.js"></script>

zmeníme na:

<script src="{% static 'js/jquery.js' %}"></script>

Statický obsah sa teraz načita bez problémov. Ostáva vyriešiť už iba linky v menu. Pôvodné menu vyzeralo nasledovne:

<ul class="nav navbar-nav">
    <li>
        <a href="#">O pekárni</a>
    </li>
    <li>
        <a href="produkty.html">Produkty</a>
    </li>
    <li>
        <a href="kontakt.html">Kontakt</a>
    </li>
</ul>

My ho však upravíme s využitím django templates:

<ul class="nav navbar-nav">
    <li>
        <a href="#">O pekárni</a>
    </li>
    <li>
        <a href="{% url 'produkty' %}">Produkty</a>
    </li>
    <li>
        <a href="{% url 'kontakt' %}">Kontakt</a>
    </li>
</ul>

produkty a kontakt sú názvi, ktoré sme uviedli do parametru name= v nazovaplikacie/urls.py.

Zmena statickej stránky na dynamickú je dokonaná. Google analytics sa nasadí do scaffold.html do pätičky a načíta sa pri každej stránke na webe. Teraz môžeme pridať do menu novú položku. Vlastne tam ani nič nové nebude, len sa zopakuje postup vyšie:

  • vytvorí sa nová šablona v templates/
  • pridá sa záznam do nazovaplikacie/urls.py
  • pridá sa nový item do menu

Ende

V ďalšej epizóde si ukážeme ako aplikáciu deploynuť na produkciu s využitím Gunicorn, Nginx, a Docker.