Flask kniha aneb jak dostat Python na web Ondrej Sika 3. 3. 2015
1
Flask kniha aneb jak dostat Python na web Ondrej Sika
[email protected] http://ondrejsika.com
Domovska stranka knihy je https://ondrejsika.com/books/flask-kniha 2
Venovano Karoline, Barbore a Renate Sikove 3
Contents 1 Uvod 1.1 Predmluva . . . . . . . . . . . . . . . . . . . . 1.2 Co je to Flask? . . . . . . . . . . . . . . . . .
6 6 6
2 Instalace
8
3 Zakladni struktura 9 3.1 Hello world . . . . . . . . . . . . . . . . . . . 9 3.2 Zakladni struktura . . . . . . . . . . . . . . . 10 3.3 Debug . . . . . . . . . . . . . . . . . . . . . . 10 4 Pohledy 12 4.1 Request objekt . . . . . . . . . . . . . . . . . 12 4.2 Request methods . . . . . . . . . . . . . . . . 13 5 HTML 5.1 Syntaxe . . . . . . . . . . . 5.2 Zakladni formatovaci prvky 5.3 Odkazy . . . . . . . . . . . . 5.4 Formulare . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
15 15 15 16 17
6 Sablony 6.1 Promenne . . . . . . . . . 6.1.1 Predane z pohledu 6.1.2 Definice v sablone . 6.2 Vkladani (include) . . . . 6.3 Rozsirovani (extends) . . . 6.4 Podminky . . . . . . . . . 6.5 Cykly . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
19 19 20 21 21 22 23 23
. . . . . . .
7 Data od uzivatele 25 7.1 Parametry v URL . . . . . . . . . . . . . . . . 25
4
7.2 7.3
GET . . . . . . . . . . . . . . . . . . . . . . . 25 POST . . . . . . . . . . . . . . . . . . . . . . 26
8 Databaze (Dataset) 8.1 Pripojeni k databazy 8.1.1 Sqlite . . . . 8.1.2 PostgreSQL . 8.1.3 MySQL . . . 8.2 Ukladani dat . . . . 8.3 Nacitani dat . . . . . 8.4 Informace o databazi
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
27 27 28 28 28 29 29 30
9 Session
31
10 Deployment 10.1 Deploy2 . . . . . 10.2 Cloud . . . . . . 10.2.1 Heroku . . 10.2.2 Openshift 10.3 Rucne . . . . . . 10.3.1 Gunicorn 10.3.2 Supervisor 10.3.3 Nginx . .
32 32 32 32 32 32 32 33 34
. . . . . . . .
. . . . . . . .
11 Shrnurti
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
35
5
1 1.1
Uvod Predmluva
Tato kniha je moji druhou knihou pro zacinajici programatory. V te prvni (Python kniha, http://url.os1.cz/pythonkniha) jsem popisoval uplne zacatky programovani v Pythonu. Tato kniha navazuje na predchozi, tim ze vse co umime chceme dat na web a umoznit uzivateli jednoduchou interakci. Kniha si neklade za cil naucit vas tvorit webove stranky (na to jich je spousta), ale ukazat ze programovani webu v Pythonu neni tak slozite a za PHP neni jedinou cestou jak delat weby. V knize je hodne ukazek kodu, repozitar s temito ukazkami je: http://url.os1.cz/flask-kniha-code-examples Odkaz najdete i na homepage knihy. Preji aby cteni bylo prijemne a posunulo vase znalosti v programovani webovych aplikaci.
1.2
Co je to Flask?
Flask je micro framwork pro tvorbu webu pro Python. Framework zamena ze je to soubor funkci, ktere nam zjednodusuji psani vlastnio kodu. Mohli bychom psat webovy server sami, ale zabralo by nam to hodne casu, museli bychom se hodne veci naucit a vysledek 6
by nebyl lepsi nez ted. Existuji i jine frameworky pro tvorbu webu v Pythonu, nejznamejsi je z nich Django, ktere je ovsem o hodne slozitejsi, ale umi toho vic. Flask ma vyhody ze je velmi jednoduchy a vsechno se na nem da hezky posat a vysvetlit. Django ma podobnou strukturu, ale je mnohem komplikovanejsi pro zacatecnika zbytecne. Domovska stranka Flasku je http://flask.pocoo.org, kde najdete veskerou dokumentaci a podrobne priklady pouziti. Vyhodou Flasku o proti Djangu je i start nove aplikace rychlejsi a jednodusi. Zatimco django ma nekolik adresaru a musi se nastavit pomerne hodne hodnot nez se da vubec spustit, Flask aplikace je v jednom souboru a nic zvlastniho se nastavovat nemusi.
7
2
Instalace
Predpokladejme ze Python a virtualenv mame nainstalovany.
8
3 3.1
Zakladni struktura Hello world
Ukazeme si tradicne prvni ukazkovou aplikaci ktera zobrazi v prohlizeci text ”Hello world”. Priklad 01: Soubor: app.py from flask import Flask app = Flask(__name__) @app.route(’/’) def view(): return ’Hello world’ if __name__ == ’__main__’: app.run() Je takova konvence, ze hlavni soubor flask aplikace se jmenuje app.py, ja se ji budu drzet. Tento kod spustime jako standartni Python program: python3 app.py Program se spusti a vypise do terminalu: * Running on http://127.0.0.1:5000/ To znamena, ze je vse OK a mame si v prohlizeci otevrit url ”http://127.0.0.1:5000/”. Kdyz se na ni podivame, uvidime na strance text ”Hello world”.
9
3.2
Zakladni struktura
Na tomto prikladu si muzeme ukazat jednotlive casti kodu a trosku si je popsat. Prvni radek je pouze import flasku. Na druhem se inicializuje Flask WSGI objekt, coz je neco jako kostra cele aplikace. Na tu se poto pripinaji ruzne pohledy (views). Prave takovy pohled je v treti casti kodu. Dekorator ”app.route” aby se dana funkce vykonala pri dotazu na konkretni url, v nasem pripada na ”/”. Posledni cast je jenom prikaz spuseni serveru, pokud soubor chceme spustit. Pokud jej budeme importovat napriklad do Gunicornu (WSGI server), kod se neprovede a server se nespusti. O to se pak stara Gunicorn.
3.3
Debug
Pokud mam aplikaci v produkcnim prostredi, nechci aby pri chybe vypisovala chybove hlasky a uz vubec ne aby pri chybe byla dostupna debug konzole. Proto je tato funkcionalita by default vypnuta. Ale pri vyvoji se hodi presny popis chyb i konzole. Pro zapnuti debug rezimu staci pridat k ”app” attribut ”debug = True”. if __name__ == ’__main__’: app.debug = True app.run() Ukazka 02 - aplikace v debug modu s chybou Je lepsi to dat az za podminku lokalniho spousteni, aby tuto informaci nedostaval externi WSGI serve, napriklad Guni10
corn. Dale se take debug mod hodi, protoze pri editaci zdrojoveho souboru automaticky restartuje server, coz je velmi prijemne.
11
4
Pohledy
Pohledy (neboli views) jsou funkce ktere se volaji pri pristupu na danou url ktera je definovana v dekoratoru ”app.route”. Pohledu muze byt v aplikaci neomezene, kazde musi mit ovsem unikatni pojmenovani funkce. Priklad 03: from flask import Flask app = Flask(__name__) @app.route(’/’) def first_view(): return ’First’ @app.route(’/second/’) def second_view(): return ’Second’ if __name__ == ’__main__’: app.debug = True app.run()
4.1
Request objekt
Request objekt obsahuje ruzna data z requestu, muzete k nim pristupovat prez objekt ”request” s ruznymi atributy. Request objekt musime nejdrive naimportovat: from flask import request Potom se z pohledu muzete ptat na jeho atributy: 12
@app.route(’/’) def some_view(): return "url: %s, path: %s" % (request.url, request.path Ted si popiseme nejake zakladni atributy requestu, podrobnejsi popis a popis vsech atributu naleznete v dokumentaci. • form - obsahuje POST data (z formulare) • args - obahuje GET data (z url) • headers - obsahuje http hlavicky • data - obsahuje telo requestu (vhodne pro RPC) • files - obsahuje uploadovane soubory • method - obsahuje metodu requestu (POST, GET etc.) • path - obsahuje cestu za domenou (/about-me/) • url - obsahuje celou url (https://ondrejsika.com/aboutme)
4.2
Request methods
Pokud chceme vyuzivat jine requesty nez GET, musime to povolit v ”app.route”. Musime je definovat v atributu methods. @app.route(’/’, methods=[’GET’, ’POST’]) def first_view(): return ’First’ @app.route(’/second/’, methods=[’POST’]) def second_view(): return ’Second’ 13
Na prvni view se dostaneme objema typy requestu, na druhy pouze metodou POST.
14
5
HTML
V teto kapitole chci popsat jen par prvku, ktere se pouzivaji pro interakci s aplikaci, odkazy, formulare, ... Nechci vysvetlovat HTML detailne, navodu a knizek je plny internet. Jsou i v cestine.
5.1
Syntaxe
Syntaxe vychazi z XML, to znamena ze jednotlive tagy jsou uzavreny v
. Existuji 2 druhy tagu, parove a neparove. Prikladem paroveho tagu je nadpis: Nadpis
Prikladem neparoveho tagu je zalomeni radky:
5.2
Zakladni formatovaci prvky
Aby nase aplikace mela alespon nejakou strukturu, popiseme si par zakladnich formatovacich prvku. Nadpisy Mame nadpisy h1 az h6, h1 je nejvissi uroven a h6 nejnizsi.
15
Nadpis
Nadpis
Nadpis
Nadpis
Nadpis
Nadpis
Text Odstavec textu je uzavren v tagu ”p”, zalomeni radky se dela momoci tagu ”br”. Nejaky text
dalsi radka
5.3
Odkazy
Odkazy se pouzivaji pro pohyb mezi strankami (pohledy). Obcas mohou udelat nejakou akci nebo neco nastavit. Odkazy pouzivaji parovy tag ”a” s jednim povinym parametrem ”href”, ktery ukazuje kam se ma uzivatel presunout po kliknuti na odkaz. Nejaky text odkaz Tato ukazka odkazuje na stranku ”/o-nas/”. Aby straka spravne fungovala, musi mit pohled se spravnou routou. @app.route(’/o-nas/’) def o_nas_view(): ...
16
5.4
Formulare
Formulare primarne slouzi k zadavani vstupnich dat od uzivatele. Maji 2 rezimy, jak posilaji data serveru GET a POST. GET parametry jsou predany v url a post parametry v tele requestu. GET parametry se pouzivaji pro formulare ktere nastavuji nejake hodnoty treba ve filtrovani a POST se pouziva pro vetsinu ostatnich formularu, vcetne prihlasovani. Formular se sklada z tagu ”form” a tagu vstupnich poli. Jsou to tagy input, textarea, select. Select ma v sobe jeste opton tagy. Jednoduchy formular co podesle nejakou hodnotu pocet v GET parametru. Tag ”form” ma par atributu, ktere je dobre znat. • action - stranku na kterou posila pozadavek, pokud neni vyplnen pouzije soucasnou. • method - vyber poslani parametru metodou GET nebo POST. Pokud neni nastaven, pouzije defaultne GET.
Kdyz se trochu podivame na tento kratky formular, vidime ze se posle na url ”/soucet/” a parametry budou ”prvni” a ”druhy”. Input type submit je tlacitko pro odeslani.
17
Kdyz vime ze se parametry predaji momoci GET, pokud vyplnime cisla 1 a 2, url bude vypadat takto: ”/soucet/?prvni=1&druhy=2”. I inputy mohou mit atribut value, ten nastavuje defaultni hodnotu. Pokud jej nevyplnime, pole zustanou prazdne. Toto jsou zaklady prace s formularema, vice informaci urcite najdete na internetu.
18
6
Sablony
Sablony jsou HTML soubory ktere jsou renderovane sablonovacim jazykem Jinja2 (od stejnych autoru jako flask). Sablony piseme do zvlastniho adresare ”templates”, tam je hleda funkce ”render template”, ktera zajistuje renderovani Jinja2. Priklad 04: Soubor: app.py from flask import Flask app = Flask(__name__) @app.route(’/’) def view(): return flask.render_template(’index.html’) if __name__ == ’__main__’: app.debug = True app.run() Soubor: templates/index.html Hello from template Se sablonami Jinja2 umi delat kouzla, my si ukazeme jenom nektere zakladni z nich.
6.1
Promenne
Zakladni funkcionalita, ktera je nezbytna pro praci s sablonami, jsou promenne. Promenne se zapisuji do dvojtych slozenych zavorek. Takto se do template vlozi promenna: 19
{{ promenna }} 6.1.1
Predane z pohledu
Do sablony muzeme dosazovat promenne nejcasteji z pohledu a pracovat s nimi. a nastavuji se funkci ”render template” jako kwargs. Priklad 05: Soubor: app.py @app.route(’/’) def view(): now = datetime.datetime.now() return flask.render_template(’index.html’, now=now) Soubor: templates/index.html Now is {{ now }} Promennych muze byt dosazeno samozrejmne vice: @app.route(’/’) def view(): now = datetime.datetime.now() timestamp = time.time() return flask.render_template(’index.html’, now=now, timestamp=timestamp) Soubor: templates/index.html Now is {{ now }}, timestamp is {{ timestamp }}.
20
6.1.2
Definice v sablone
Promennou muzete take zadefinovat primo v sablone. Dela se to velmi jednoduse, pomoci tagu ”set”. Soubor: templates/index.html {% set name = ’Ondrej’ %} Hello {{ name }}! a do browseru vypise ”Hello Ondrej!”
6.2
Vkladani (include)
Pokud do sablony chceme vlozit jiny soubor, muzeme pouzit tag include. Soubor: templates/index.html Hello from template {% include ’footer.html’ %} Soubor: templates/footer.html
My awesome site
V prohlizeci pak uvidite: Hello from template My awesome site Do includovane sablony se predavaji vsechny promenne, takze je muzete pouzivat. Pokud promennou nemate definovanou, muzete ji zadefinovat primo v include tagu. Soubor: templates/index.html Hello from template 21
{% include ’footer.html’ with author=’Ondrej Sika’ %} Soubor: templates/footer.html
My awesome site ({{ author }})
V prohlizeci pak uvidite: Hello from template My awesome site (Ondrej Sika)
6.3
Rozsirovani (extends)
Extends se v praxi pouziva mnohem vice nez include. Rozsirovani funguje obracene nez include. Nami definovane bloky z aktualni sablony vlozi na bloky sablony definovane v tagu ”extends”. Priklad s patickou muzeme prepsat s pouzitim ”extends”. Tag extends musi byt jako prvni v sablone. Definice bloku je mezi ”{% block %}” a ”{% endblock %}”. Soubor: templates/index.html {% extends ’base.html’ %} {% block content %} Hello from template {% endblock content %} Soubor: templates/base.html {% block content %}{% endblock %}
My awesome site
V prohlizeci pak uvidite to same jako s pouzitim include: Hello from template My awesome site 22
Na tomto kratkem prikladu se to zda zbytecne. Vyhodou je ze pokud chete definvat vice mist kam neco vkladat dynamicky a nekde mit zakladni prvky, staci mit pouze jeden base.html a vice blocku, s pouzitim include by to bylo velmi obtizne a museli by jste pouzit vice nez 1 vlozeny soubor.
6.4
Podminky
V sablonach muzeme vyuzivat podminky IF. Jeji syntaxe je velmi intuitivni. {% if variable %} Value is {{ variable }} {% endif %} Nebo muzeme pouzit jeste pouzit block else. Potom to vypada takthe. {% if variable %} Value is {{ variable }} {% else %} No value {% endif %}
6.5
Cykly
V sablone pouzivame pouze for cyklus. {% for element in iterable %}
Prvek je "{{ element }}"
{% endif %}
23
Pokud chceme v cyklu zjistit, kolikata je to iterace slouzi nam k tomu promenna ”loop.index”. {% for element in iterable %}
Prvek je {{ loop.index }} "{{ element }}"
{% endif %} Pokud mame v promenne iterable seznam ”[’a’, ’b’, ’c’]”, potom prvni cyklus vypise: Prvek je "a" Prvek je "b" Prvek je "c" A druhy vypise: Prvek 1 je "a" Prvek 2 je "b" Prvek 3 je "c"
24
7
Data od uzivatele
Uz umime delat mozne i nemozne veci se sablonami, udelat vice stranek, ale zatim neumime komunikovat s uzivatelem, respektive neumime ziskad od neho nejaka dynamicka data. A k tomu je tato kapitola.
7.1
Parametry v URL
Pokud chceme mit elegani url bez nejakych otazniku a rovnase, muzeme definovat promenne jako soucast url. Toto je podle me (i podle Google) lepsi url ”/article/new-article/” nez ”/article/?slug=new-article”. Jak to udelat? Do definice cesty v app route musime pridat parametr promenne a do funkce ktera definuje pohled jeden argument. Vypada to takto: @app.route(’/article/<slug>/’) def article_view(slug): # ...
7.2
GET
Pokud mame hodne ruznych atributu, kde nezalezi na poradi a ani na tom jak bude vypadat url, je vhodnejsi pouzit GET parametry. URL pak muze vypadat takto ”/api/?version=1&key=time” K temto atributum pristupujeme ve Flasku prez promennou ”flask.request.args”. Musime ji nejdriv importovat.
25
from flask import request @app.route(’/api/’) def api_view(): version = request.args.get(’version’) key = request.args.get(’key’) # ...
7.3
POST
U POST atributu je to podobne. POST atributy jsou vetsinou z nejakeho formulare, proto se k nim ve Flasku pristupujeme prez promenou ”request.post”. Nezapomente na to ze v zakladu je v seznamu povolenych meod pouze GET, pokud chete pohled pouzivat s metodou POST, musite ji v hlavicce povolit. from flask import request @app.route(’/form/’, methods=[’POST’]) def form_view(): name = request.form.get(’name’) email = request.form.get(’email’) # ...
26
8
Databaze (Dataset)
Pristup do databaze prez sql je nad ramec teto knihy, proto popisu pristup k datazi prez velmi jednoduche ORM datasets. Jak auto popisuje ”Database for lazy people”. Pristup je velmi jednoduchy a datasets umi komunikovat s SQLite, PostgreSQL i MySQL.
8.1
Pripojeni k databazy
Pripojeni se vytvori funkci ”dataset.connect” a jeji parametr je connection string. Obecny connection string ma tuto podobu: ’dialect://user:password@host/dbname’ Jednotlive casti znamenaji toto: • dialect - druh databaze (sqlite, postgres, ...) • user, password - prihlasovaci udaje k databazi • host - stroj na kterem databaze bezi • dbname - nazev databaze Ukazka pripojeni k SQLite: import dataset db = dataset.connect(’sqlite:///:memory:’) Tato ukazka je pripojeni k SQLite, databazi v souboru, ktera nevytvori databazovi soubor, ale zustane v pameti po dobu
27
behu prrogramu. Toto pripojeni k databazi budu pouzivat u vetsiny ukazek. 8.1.1
Sqlite
SQLite je v Pythonu nativne podporovana, proto neni treba instalovat zadne knihovny. Pripojeni ke klasickemu SQLite databazovemu souboru vypada takto. db = dataset.connect(’sqlite://test.sqlite3’) Pripojeni do databaze v pameti je predchozi priklad. 8.1.2
PostgreSQL
Pro pouziti postgresu je nutne mit naistalovanou knihovnu ”psycopg2”. Nainstaluje ji prikazem: pip3 install psycopg2 Connectionstring potom vypada takto:
db = dataset.connect(’postgresql://postgres:pg@localhost:54 8.1.3
MySQL
Pouziti MySQL je stejne jako Postgresu. Take je potreba doinstalovat knihovnu na praci s MySQL ”mysqldb”. pip3 install mysql-db Ukazka mysql connection stringu: db = dataset.connect(’mysql://root:asdf@localhost/test’) 28
8.2
Ukladani dat
Data se uladaji do db ve formatu slovniku. Struktura se vytvari dynamicky, neni treba predem definovat. To je velmi prijemne. Pokud chceme pridat uzivatele do tabulky users (pokud tabulka neexistuje tak si ji dataset vytvori), staci zavolat na tabulku metodu insert se slovnikem s daty. table = db[’user’] table.insert({’name’: ’sika’, ’country’: ’CZ’}) table.insert({’name’: ’karel’, ’country’: ’CZ’}) Pokud budeme chtit pridat vice dat, dataset sam prida dalsi sloupecky.
table.inser({’name’: ’novak’, ’country’: ’SK’, ’pass’: ’hes Pokud v tabulce jsou nejaka data, nove sloupecky budou null.
8.3
Nacitani dat
Do promenne users nacte vsechny radky z DB. users = db[’user’].all() Nebo se da pouzit bez te metody all. for user in db[’user’]: print(user[’name’]) Nacte seznam vsech ceskych uzivatelu. czech_users = table.find(country=’CZ’) Vybere jeden radek. 29
sika = table.find_one(name=’sika’) Vybere unikatni zaznamy podle zeme. Pro kazdy stat bude vracen jeden uzivatel. db[’user’].distinct(’country’)
8.4
Informace o databazi
Tabulky v databazi >>> print(db.tables) [u’user’] Sloupecky tabulky >>> print(db[’user’].columns) [u’id’, u’country’, u’age’, u’name’, u’gender’] Pocet radku v tabulce >>> print(len(db[’user’])) 2
30
9
Session
Pro pouzivani sessions je dulezite pro jejich bezpecnost mit nastaveny secret key. Je dobre ho nastavit hned za inicializaci Flasku. app = Flask(__name__) app.secret_key = ’ultra safe key’
31
10
Deployment
10.1
Deploy2
10.2
Cloud
10.2.1
Heroku
10.2.2
Openshift
10.3
Rucne
10.3.1
Gunicorn
Gunicorn je asynchroni WSGI server, ktery je navrzen na produkcni provoz. Muzeme samozrejme pouzit ”app.run()”, ale vetsi zatez by tento server nezvladnul. Gunicorn nainstalujeme prikazem: apt-get install gunicorn Gunicorn ma hodne moznosti behu, ale nam bude stacit zakladni nastaveni. Ma jako argument nazev ”souboru:wsgi app”. Pro nas to je ”app:app”. Potom je pro nas dulezity -b, to je parametr ktery nastavuje kde posloucha muzeme pouzit unix socket nebo host a port. Ukazka spusteni host a port: gunicorn app:app -b ’127.0.0.0:8000’ gunicorn app:app -b ’unix:///tmp/testapp.sock’
32
K unix socketu se pote pripoji nginx, ktery bude nase data dale servirovat svetu. 10.3.2
Supervisor
Supervizor spravuje ruzne bezici procesy v systemu, zarizuje spusteni procesu po startu systemu atd. Supervisor ma konfiguracni soubory v ”/etc/supervisor” a vlastni konfiguracni soubory piseme do ”/etc/supervisor/conf.d/” s priponou ”.conf”. V konfiguracnim souboru je jmeno aplikace, prikaz kterym se spousti a adresar ze ktereho se spouzti. To nam pro zacatek staci. Ukazka supervisor konfigurace pro gunicorn s unix socketem: Soubor ”/etc/supervisor/conf.d/testapp.cz.conf”: [application:testapp] ... Po pridani konfigurace musime prenacist supervisor, dela se to prikazem: supervisor reload Za par vtenin aplikace nabootuje. Pokud chcete aplikaci vypnout, zapnout nebo restartovat, pouzijte tyto prikazy: supervisor stop testapp supervisor start testapp supervisor restart testapp Pokud aplikaci zmenite, nebo nasadite novou verzi, je nutne potom provest jeji restart.
33
10.3.3
Nginx
Nginx je webovy server, ktery funguje jako proxy server k nasemu aplikacnimu serveru (gunicorn). Take se stara o staticke soubory. Je napsany v C a proto je hodne rychly. Nginx nainstalujeme prikazem: apt-get install nginx Konfiguracni soubory jsou v ”/etc/nginx”. Definice jednotlivich serveru (mysleno aplikace) se nachazi v ”/etc/nginx/sitesavailable”. Vytvorte tam soubor treba podle domeny: Soubor /etc/nginx/sites-available/testapp.cz: server { listen 80; # ... } Pokud chcete tuto aplikaci spustit, musite pridat symlink do adresare ”/etc/nginx/sites-enabled”. Link vytvorime takto: ln -s /etc/nginx/sites-available/testapp.cz \ /etc/nginx/sites-enabled/ Potom staci jen restartovat nginx prikazem: service nginx restart
34
11
Shrnurti
Doufam, ze vam tato kniha dala potrebne rady k tomu, jak si zprovoznit svuj prvni web na Pythonu. Doufam, ze se vam libila. Prosim, napiste mi vas nazor a pripominky na
[email protected] a neco tweetnete :) Za zpetnou vazbu budu velmi rad.
35