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 2022-2023

Framework Django – první aplikace

(připomenutí z minulého týdne)

Django – instalace

Jeden z následujících příkazů (v závislosti na instalaci Pythonu):

  • pip install django – pokud je k dispozici příkaz pip
  • pip3 install django – pokud je k dispozici příkaz pip3
  • python -m pip install django – pomocí modulu pip
  • py -m pip install django – pokud je Python interpreter dostupný jako py

Ověření:

  • příkaz django-admin --version v terminálu,
  • nebo příkaz python -m django --version – pomocí modulu django,
  • nebo příkaz py -m django --version – pokud je Python interpreter dostupný jako py namísto python

Django – vytvoření projektu

V adresáři, kde chcete vytvořit projekt, spusťte příkaz:

django-admin startproject mysite

Pokud není k dispozici příkaz django-admin, totéž lze provést pomocí modulu django

python -m django startproject mysite

Případně použijte py místo python.

Django – přidání aplikace do projektu

V adresáři projektu spustíme skript manage.py:

python manage.py startapp pokus

Případně použijte py místo python.

Django – spuštění vývojového serveru

V adresáři projektu spustíme skript manage.py:

python manage.py runserver

Mapování URL na view

views.py:

from django.http import HttpResponse

def index(request):
    return HttpResponse("<b>Hello, world!</b>")

urls.py:

from django.contrib import admin
from django.urls import path

from pokus import views

urlpatterns = [
    path("", views.index),
    path('admin/', admin.site.urls),
]

Modely pro síťovou komunikaci

OSI model

OSI model vznikl v 1983 jako abstraktní základ pro standardizaci komunikačních protokolů.

  • je rozdělen do 7 vrstev, každá má své dobře definované funkce
  • nespecifikuje konkrétní sadu protokolů

Internet protocol suite (TCP/IP)

Internet protocol suite je sada komunikačních protokolů používaná v síti Internet.

  • má jen 4 vrstvy, je to praktická aplikace modelu OSI
  • název pochází ze dvou nejdůležitějších protokolů: TCP a IP

Srovnání modelů OSI a TCP/IP

center contain

TCP/IP – vrstva síťového rozhraní (link layer)

Nejnižší vrstva umožňuje přístup k fyzickému přenosovému médiu. Je specifická pro každou síť v závislosti na její implementaci.

Příklady sítí: Ethernet, Wi-Fi, ADSL, PPP, ...

  • stará se o fyzický přenos dat
  • základní jednotka přenosu: rámec (v OSI modelu bity na fyzické vrstvě)

TCP/IP – síťová vrstva (internet layer)

Vrstva zajišťuje především síťovou adresaci, směrování a předávání datagramů.

  • nezávisí na konkrétní přenosové technologii (využívá vrstvu síťového rozhraní)
  • je implementována ve všech prvcích sítě (směrovače i koncová zařízení)
  • hlavní protokol: IP (IPv4, IPv6)
    • základní přenosová jednotka: IP datagram
    • adresní mechanismus: IP adresa (např. 192.168.0.10, fe80::862a:fdff:fe0f:fbd)
    • směrovací schéma pro přenos dat
  • další protokoly: ARP, RARP, ICMP, IGMP, IGRP, IPSEC, ...

TCP/IP – transportní vrstva (transport layer)

Poskytuje transportní služby pro dvojice aplikačních programů (koncových uzlů), tj. entity bezprostředně vyšší vrstvy.

  • je implementována až v koncových zařízeních (počítačích)
  • míra spolehlivosti přenosu závisí na zvoleném protokolu (odpovídá potřebám aplikace)
  • umožňuje přizpůsobit chování sítě potřebám aplikace

TCP/IP – nejběžnější protokoly transportní vrstvy

  • TCP (transmission control protocol)
    • spolehlivý transportní protokol (přeposílá ztracené packety, zajišťuje doručení ve správném pořadí)
    • z hlediska aplikace se přenos dat jeví jako spojitý proud
    • po navázání spojení je přenos plně duplexní (tok dat oběma směry)
  • UDP (user datagram protocol)
    • nespolehlivý protokol (neposkytuje kontrolu integrity)
    • poskytuje efektivní (rychlý) přenos dat na úkor spolehlivosti
    • na rozdíl od TCP nemá fázi navazování a ukončení spojení
  • TCP i UDP používají porty pro adresování dat jednotlivým aplikacím

TCP/IP – porty v protokolu TCP

Síťový port v protokolech TCP a UDP je číselné označení komunikačního bodu pro dané spojení.

  • příjemcem dat je proces, který je v danou chvíli k danému portu připojen
  • vztah mezi portem a aplikací je dynamický (procesy se dynamicky připojují a odpojují od jednotlivých portů)
  • nejběžnější čísla cílových portů: 22 (SSH), 53 (DNS), 80 (HTTP), 443 (HTTPS)

contain center

TCP/IP – aplikační vrstva (application layer)

Aplikační vrstva zahrnuje protokoly, které slouží k přenosu konkrétních dat.

Příklady:

  • DHCP – automatická konfigurace síťových zařízení (IP adresa, maska sítě, implicitní brána, DNS server, a další)
  • DNS – hierarchický, decentralizovaný systém doménových jmen
    • mapování symbolických jmen (domén) na IP adresy
    • např. jlk.fjfi.cvut.cz: doména nejvyšší úrovně cz, doména cvut, subdoména fjfi, atd.
  • HTTP – komunikace mezi webovými servery a klienty (viz dále)
  • Telnet, SSH, FTP, POP3, IMAP, SMTP, ...

Identifikace zdrojů na webu

Potřeba jednoznačně identifikovat různé druhy objektů vedla ke specifikaci URI (uniform resource identifier). URI má dva podtypy:


contain center

Protokol HTTP

Protokol HTTP

HTTP (Hypertext Transfer Protocol) je protokol určený pro komunikaci s WWW servery. Slouží pro přenos hypertextových dokumentů ve formátech HTML, XML, a obecně libovolných souborů (např. multimédia, textové soubory).

  • používá obvykle port TCP/80
  • neumožňuje šifrování – zabezpečený protokol HTTPS (TLS spojení nad TCP/443)
  • architektura klient-server: klient vyšle požadavek (request) a od serveru obdrží odpověď (response)
  • je bezestavový – neudržuje informace o dřívějších spojeních a odeslaných datech (vzpomeňte si na REST)

Fungování protokolu HTTP

  1. navázání spojení
  2. odeslání požadavku z klienta na server
  3. odeslání odpovědi ze serveru klientovi
  4. ukončení spojení

Nejvíce času při načítání dokumentu zabere navázání spojení – zejména pro stránky s mnoha vloženými objekty. Proto vznikly různé optimalizace:

  • přenos více požadavků a odpovědí v jednom spojení, udržování trvalých spojení se serverem (keep-alive) – od verze HTTP/1.1
  • komprese hlaviček, přednostní zpracování požadavků – verze HTTP/2
  • optimalizace na úrovni transportní vrstvy s využitím UDP – verze HTTP/3

Struktura požadavku HTTP

method URL protocol
headers

message body

(Hlavičky a tělo požadavku jsou volitelné.)

Příklad:

GET /some_page/ HTTP/1.1
Host: localhost:8000
User-Agent: curl/7.88.1
Accept: */*

Struktura odpovědi HTTP

protocol status_code reason_phrase
headers

response body

(Hlavičky a tělo odpovědi jsou volitelné.)

Příklad:

HTTP/1.1 200 OK
Date: Sun, 12 Mar 2023 21:35:04 GMT
Server: WSGIServer/0.2 CPython/3.10.9
Content-Type: text/html; charset=utf-8

<!DOCTYPE html><html lang="en">...................................</html>

Metody požadavků HTTP

Metoda určuje typ požadavku, který klient od serveru požaduje. Klient může použít libovolnou definovanou metodu, daný server však nemusí podporovat všechny.

  • GET – nejčastější metoda, požadavek na dokument určený pomocí URL
  • HEAD – identická s metodou GET, ale server odešle jen hlavičky odpovědi
  • POST – odesílání dat z klienta na server pomocí těla požadavku, modifikace stavu serveru (např. uložení dat v databázi) – příklad
  • další: PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH

Stavové kódy HTTP

Stavové kódy určují obecný typ výsledku zpracování požadavku serverem. Jsou to tříciferné číselné kódy rozdělené do tematických skupin dle první číslice:

  • 1xx – informační – požadavek byl obdržen, zpracování pokračuje
  • 2xx – úspěch – požadavek byl obdržen, pochopen a akceptován
  • 3xx – přesměrování – klient musí provést další akce, aby dokončil požadavek
  • 4xx – chyba klienta – požadavek obsahuje neplatná data nebo nemůže být vyřízen
  • 5xx – chyba serveru – zpracování platného požadavku selhalo

Hlavičky HTTP

Hlavičky slouží k doplnění požadavku nebo odpovědi o metadata.

  • každá hlavička je dvojice klíč: hodnota
  • kódování hlaviček je buď textové (HTTP/1.1) nebo binární (HTTP/2 a HTTP/3)
  • příklad hlaviček požadavku:
    User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:110.0) Gecko/20100101 Firefox/110.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    
  • příklad hlaviček odpovědi:
    Content-Length: 767
    Content-Type: text/html; charset=utf-8
    Date: Mon, 13 Mar 2023 09:29:38 GMT
    Server: WSGIServer/0.2 CPython/3.10.9
    
  • seznam standardních hlaviček (lze definovat i vlastní klíče)

Protokol HTTP ve frameworku Django

Mapování URL na view

Probíhá v souboru urls.py pomocí:

  1. funkce path(), která zpracovává jednoduché vzory:
    from django.urls import path
    
    urlpatterns = [
        path('index/', views.index, name='main-view'),
        path('bio/<username>/', views.bio, name='bio'),
        path('articles/<slug:title>/', views.article, name='article-detail'),
        path('articles/<slug:title>/<int:section>/', views.section, name='article-section'),
    ]
    
  2. funkce re_path(), která zpracovává regulární výrazy:
    from django.urls import re_path
    
    urlpatterns = [
        re_path(r'^index/$', views.index, name='index'),
        re_path(r'^bio/(?P<username>\w+)/$', views.bio, name='bio'),                       #
    ]
    

Více informací v dokumentaci.

Objekty HttpRequest a HttpResponse

Funkce index ze slajdu 6 má parametr request (objekt typu HttpRequest), a vrací objekt typu HttpResponse.

Objekty slouží pro abstrakci dat přenášených pomocí protokolu HTTP(S).

Více informací o objektech v dokumentaci Django.

Atributy objektu HttpRequest

Pouze read-only atributy:

  • HttpRequest.scheme – schéma požadavku (typicky "http" nebo "https")
  • HttpRequest.method – metoda protokolu HTTP (např. "GET" nebo "POST")
  • HttpRequest.path – část URL odpovídající cestě k danému dokumentu
  • HttpRequest.GET – slovník obsahující parametry odeslané metodou GET
    (odpovídá části URL, tzv. query string: např. ?a=123&b=4)
  • HttpRequest.POST – slovník obsahující parametry odeslané metodou POST
    (typicky kódované v těle požadavku, Django se stará o dekódování dle hlaviček)
  • HttpRequest.headers – slovník obsahující hlavičky (klíče jsou case-insensitive)
  • další: HttpRequest.COOKIES, HttpRequest.FILES, HttpRequest.META

Parametry objektu HttpResponse

Tvar konstruktoru objektu:

HttpResponse.__init__(content=b'', content_type=None, status=200, reason=None, charset=None, headers=None)
  • content – tělo odpovědi (typicky string obsahující dokument ve formátu HTML)
  • content_type – defaultní hodnota "text/html; charset=utf-8"
  • status – stavový kód (číslo nebo objekt http.HTTPStatus)
  • reason – fráze stavu odpovědi (defaultně se vybere podle stavového kódu)
  • charset – kódování odpovědi (defaultní hodnota se parsuje z content_type)
  • headers – slovník s hlavičkami odpovědi

Metody objektu HttpResponse

  • HttpResponse.write() – slouží k postupnému sestavování těla odpovědi, např.:
    response = HttpResponse()
    response.write("<p>Here's the text of the web page.</p>")
    response.write("<p>Here's another paragraph.</p>")
    
  • operátor [] – slouží k manipulaci s hlavičkami odpovědi, např.:
    response = HttpResponse()
    if "Age" not in response:
        response["Age"] = 120
    if "Expires" in response:
        del response["Expires"]
    
  • další: viz dokumentace

Šablonový systém frameworku Django

Šablonový systém pro tvorbu dokumentů

  • tvorba dokumentu HTML pomocí postupné konstrukce stringu je nepřehledná a náchylná k chybám (v předchozích příkladech jsme navíc nekonstruovali celý dokument HTML, ale jen část <body>)
  • pro zjednodušení webové frameworky typicky poskytují nějaký způsob tvorby dokumentů na základě šablon, do kterých se doplní dynamický obsah
  • ve frameworku Django lze použít buď Django template language nebo Jinja2
  • princip: oddělení prezentace (struktury dokumentu) od logiky programu

Přidání šablony do vlastní aplikace

  1. Vytvořit adresář pro šablony: pro aplikaci pokus je to pokus/templates/pokus/
    (vnitřní adresář pokus umožňuje jednoznačně identifikovat šablony dané aplikace pomocí relativní cesty vzhledem k templates, např. pokus/base.html)
  2. Vytvořit šablony, např. base.html a some_page.html:
    └── pokus
        ├── admin.py
        ├── apps.py
        ├── __init__.py
        ├── migrations
        │   ├── __init__.py
        ├── models.py
        ├── templates
        │   └── pokus
        │       ├── base.html
        │       └── some_page.html
        ├── tests.py
        └── views.py
    

Přidání šablony do vlastní aplikace

  1. V souboru settings.py registrovat danou aplikaci, např.
    INSTALLED_APPS = [
        "pokus",
        ...
    ]
    
  2. V souboru views.py použít danou šablonu pomocí funkce render(), např.
    from django.shortcuts import render
    
    def some_page(request):
        context = {
            "some_parameters": {"key": "value"},
        }
        return render(request, "pokus/some_page.html", context)
    

Příklad – šablona base.html

{% load static %}

<!DOCTYPE html>
<html lang="{{ lang | default:'en' }}">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% block title %}{% endblock %}</title>
        <link rel="stylesheet" type="text/css" href="{% static "pokus/pokus.css" %}">
        {% block head %}
        {% endblock %}
    </head>
    <body>
        <header>
            <nav>
                <a href="{% url 'some_page' %}">Home</a>
                <a href="{% url 'some_page' %}/subpage-1">Subpage 1</a>
                <a href="{% url 'some_page' %}/subpage-2">Subpage 2</a>
            </nav>
        </header>
        <main id="content">
            {% block content %}
            <article id="content-left">
                {% block content_left %}
                {% endblock %}
            </article>
            <aside id="sidebar">
                {% block sidebar %}
                {% endblock %}
            </aside>
            {% endblock %}
        </main>
        <footer>
            <p>Powered by <a href="https://www.djangoproject.com/">Django</a>.</p>
        </footer>
    </body>
</html>

Příklad – šablona some_page.html

{% extends "pokus/base.html" %}
{% load static %}

{% block title %}
Some page title
{% endblock %}

{% block head %}
    <link rel="stylesheet" type="text/css" href="{% static 'pokus/some_page.css' %}">
{% endblock %}

{% block content %}
<article>
<section>
    <p>Li Europan lingues es membres del sam familie. Lor separat existentie es un myth. ...</p>
    <p>At solmen va esser necessi far uniform grammatica, pronunciation e plu commun paroles. ...</p>
</section>
<section>
    <h2>Použití proměnných v šabloně</h2>
    <dl>
    {% for key, value in some_parameters.items %}
        <dt>{{ key }}</dt>
        <dd>{{ value }}</dd>
    {% endfor %}
    </dl>
</section>
</article>
{% endblock %}

Syntaxe šablonového jazyka Django

  1. Proměnné: {{ variable }}, {{ object.attribute }}, atd.
  2. Filtry: {{ value|default:"nothing" }}, {{ value|filesizeformat }}, atd.
    Viz seznam vestavěných filtrů
  3. Tagy: {% tag %}, kde tag je např. extends, loads, block, for, if, ...
    Viz seznam vestavěných tagů
  4. Komentáře: {# tohle je komentář #}
  5. Dědičnost: pomocí tagů extends a block (viz příklady na předchozích slajdech)
  6. Automatické escapování HTML – lze vypnout pomocí filtru safe ({{var|safe}})
    nebo tagu autoescape ({% autoescape off %} ... {% endautoescape %})

Podrobnosti najdete v dokumentaci.

Přidání statických souborů do vlastní aplikace

  1. Vytvořit adresář pro statické soubory: podobně jako v případě šablon, pro aplikaci pokus je to pokus/static/pokus/ (vnitřní podadresář pokus umožňuje jednoznačně identifikovat statické soubory dané aplikace pomocí relativní cesty vzhledem k static, např. pokus/some_page.css)
  2. Vytvořit statické soubory, např. pokus/static/pokus/some_page.css
  3. Použít statické soubory v příslušných šablonách, např.
    {% load static %}
    
    ...
        <link rel="stylesheet" type="text/css" href="{% static "pokus/some_page.css" %}">
    ...
    
  4. Pro nasazení webu v praxi jsou potřeba další kroky, kterými se zatím nebudeme zabývat.