Python RESTful webservices with Python: Flask and Django solutions
Web Development With Python and Flask
-
Upload
danandreist -
Category
Documents
-
view
261 -
download
1
Transcript of Web Development With Python and Flask
-
8/10/2019 Web Development With Python and Flask
1/62
Web Development with Python
with flask, tornado and nginx
Table of contents
This book is for
Table of contents
PREFACE
Chapter 1 - Preparation
Chapter 2 - Getting your hands dirty ith !"ello #orld$%
Chapter & - 'etting up your de(elop)ent en(iron)ent
Chapter * - +aking the app look good,
Chapter - .atabases - )ade si)ple
#hat e/ll build ne0t
Chapter - +aking the app tick,
Chapter 3 - For)s
Chapter 4 - 5ser login - ith )anage)ent
Chapter 6 - An Ad)in Panel to sa(e us allChapter 17 - Prepare for the production en(iron)ent
Features
Chapter 11 - Going online
Chapter 1 - A list of addons that )ight interest you
Flask-8abel - translate your ebsite easy
Flask-Cache - Adds cache support to your Flask application,
Flask-9ogin - Flask-9ogin pro(ides user session )anage)ent for Flask, :t
handles the co))on tasks of logging in; logging out; and re)e)bering your
users< sessions o(er e0tended periods of ti)e,
Flask-+ongoAlche)y - Add Flask support for +ongo.8 using +ongoAlche)y
Flask-=Auth - guess hat it does >
Flask-=pen:.
Flask-Testing - The Flask-Testing e0tension pro(ides unit testing utilities for
Flask,
Flask-5ploads - Flask-5ploads allos your application to fle0ibly and efficiently
handle file uploading and ser(ing the uploaded files,
-
8/10/2019 Web Development With Python and Flask
2/62
This book is dedicated to Violeta
This book is for
8eginners or ad(anced in python and total beginners in eb progra))ing ith python,
?ou should ha(e a basic python knoledge,
@uick test
1, ?ou kno ho to con(ert a string to a nu)ber and (ice-(ersa
2, Can you rite a si)ple for loop in python
&, Can you create a si)ple class
-
8/10/2019 Web Development With Python and Flask
3/62
:f the anser to all abo(e is !?E'% then go ahead, :f you don/t kno; then you really
should start ith so)e basic python, There are lots of nice and free resources on net,
:t helps if you kno a little ht)l too; like !#hat does Bh1 do % for e0a)ple,
Disclaimer:
This book is ritten by an amateur; and it/s goal is to pro(ide you Dust ith a
starting point into Python - Flask eb progra))ing and gi(ing you my own versionon
ho to do things,
An amateurFrench amateurlo(er of; fro) =ld French and ulti)ately fro) 9atin
a)atore) no), a)ator; lo(er> is generally considered a person attached to a particular
pursuit; study; or science in a non-professional or unpaid )anner, A)ateurs often ha(e
little or no for)al training in their pursuits; and )any are autodidacts self-taught>,
ikipedia>
Alternati(es better than this book,
1, The flask docu)entation itself is pretty good
2, httpe0ploreflask,co)
&, Flask #eb .e(elop)ent .e(eloping #eb Applications ith Python by +iguel
Grinberg
*, +iguel Grindberg/s blog - free
, :nstant Flask #eb .e(elop)ent by Ron .uPlain, There are e(en youtube )o(ies on flask,
: re)ind you thatYou can do things differently and more optimized!"ere : rite )y
on idea on ho things should be, :f you/re good in front-end :/) sure you ould find
better alternati(es, :f you/re good in eb-security :/) sure you/ll find better alternati(es
for e0a)ple,
http://exploreflask.com/http://exploreflask.com/ -
8/10/2019 Web Development With Python and Flask
4/62
PREFACE
Flask is )ini)al and si)ple, ?ou don/t get =R+/s; Ad)in Panels and other stuff that
.Dango has out of the bo0, ?ou can install a (ery cool ad)in panel ith Dust 1 line of
code !pip install flask-ad)in% and integrate it ith &-* lines in your app,
:t is easy to learn; poerful and co)bined ith Tornado it produces aeso)eperfor)ance e(en on a s)all HP' of 1GhI,
rite in http,google,co)trends!Flask Python%
http://www.google.com/trends/http://www.google.com/trends/http://www.google.com/trends/ -
8/10/2019 Web Development With Python and Flask
5/62
#hat you see is the trending of Flask Progra))ing, Pretty cool isn/t it
Quick preview on what well build in thisbook
A si)ple user-tracking database )anage)ent syste) ith pagination; ad)in panel;
login; security,
As e0tra e/ll discuss in the last chapter; best practices for production en(iron)ent and
opti)iIing it for a high traffic app,
-
8/10/2019 Web Development With Python and Flask
6/62
Chapter 1 - Preparation
?ou can skip this chapter if you already ha(e a linu0 en(iron)ent set up and you don/t
hat to setup a ne one,
Suggestion:
For J per )onth; : strongly suggest that you get a HP' at digitalocean,co), :n fact : ill
gi(e you a gift of J17 if you sign up no using this link you/ll recei(e the )oney in your
account after you sign in and get a ne droplet> httpgoo,glAr9(y0this is a referal link
to )e fro) .igital=cean; this ay you can say thank you for this book and get J17>
- you get a static ip; you can add (ery easy a do)ain na)e and it/s (ery fast, Ko
August 271*> you can choose locations fro) Ke ?ork; 'an Francisco; A)sterda);
'ingapore; 9ondon,
let/s get started
1. Install Uuntu latest version
. "ogin into ssh
This book assu)es that you are fa)iliar ith ter)inal co))ands and running re)ote
co))ands ith putty, :f you need help read this article
https,digitalocean,co)co))unitytutorialsho-to-log-into-your-droplet-ith-
putty-for-indos-users
Tip if you use #indos; install Putty then install httpscode,google,co)psuperputtyand you ha(e a nice putty )anag)ent ith )ultiple indos,
Co))ands to run
df -h
ifcong a
ping c 4 google.com
L if you get unknon host L - sudo nano etcresol(,conf na)eser(er 162,14,1,1 line
don> na)eser(er 4,4,4,4
sudo apt-get update && sudo apt-get upgrade
MsshN
sudo apt-get install -y openssh-server
sudo nano /etc/ssh/sshd_cong
sudo restart ssh
http://goo.gl/ArLvyxhttps://www.digitalocean.com/community/tutorials/how-to-log-into-your-droplet-with-putty-for-windows-usershttps://www.digitalocean.com/community/tutorials/how-to-log-into-your-droplet-with-putty-for-windows-usershttps://code.google.com/p/superputty/https://code.google.com/p/superputty/http://goo.gl/ArLvyxhttps://www.digitalocean.com/community/tutorials/how-to-log-into-your-droplet-with-putty-for-windows-usershttps://www.digitalocean.com/community/tutorials/how-to-log-into-your-droplet-with-putty-for-windows-usershttps://code.google.com/p/superputty/ -
8/10/2019 Web Development With Python and Flask
7/62
sudo apt-get install -y htop zip rar unrar
sudo apt-get install -y mysql-client mysql-server
sudo apt-get install -y nginx
Meb)inNsudo nano /etc/apt/sources.list
- de! http"//do#nload.#e!min.com/do#nload/repository sarge contri!
#get -q http"//###.#e!min.com/$cameron-%ey.asc-- ' sudo apt-%ey add -
sudo apt-get update
sudo apt-get install #e!min
MfailtobanNsudo apt-get install -y fail(!an
sudo nano /etc/fail(!an/$ail.conf
check that you ha(e this configuration
MsshN
enabled O true
port O ssh
filter O sshd
logpath O (arlogauth,log
)a0retry O &
sudo /etc/init.d/fail(!an restart
sudo fail(!an-client status
sudo apt-get install -y !uild-essential python python-dev python-pip python-
mysqld! li!mysqlclient-dev supervisor li!memcached-dev memcached
python-memcache
pip install )as% )as%-login )as%-mail sqlalchemy )as%-sqlalchemy )as%-#tf
)as%-migrate tornado )as%-cache simpleencode
pip install pdfminer )as%-admin )as%-security
http://download.webmin.com/download/repositoryhttp://www.webmin.com/jcameron-key.aschttp://download.webmin.com/download/repositoryhttp://www.webmin.com/jcameron-key.asc -
8/10/2019 Web Development With Python and Flask
8/62
#gin$ pronounced engine-0> is an open source re(erse pro0y ser(er for "TTP;
"TTP'; '+TP; P=P&; and :+AP protocols; as ell as a load balancer; "TTP cache;
and a eb ser(er origin ser(er>, The ngin0 proDect started ith a strong focus on high
concurrency; high perfor)ance and lo )e)ory usage,
%emin is a eb-based syste) configuration tool for 5ni0-like syste)s; although recent
(ersions can also be installed and run on #indos, #ith it; it is possible to configure
operating syste) internals; such as users; disk uotas; ser(ices or configuration files; asell as )odify and control open source apps; such as the Apache "TTP 'er(er; P"P or
+y'@9,
-
8/10/2019 Web Development With Python and Flask
9/62
&ailan is softare to protect co)puter ser(ers fro) single-source brute-force attacks,
Fail2ban is an intrusion pre(ention fra)eork ritten in the Python progra))ing
language, :t is able to run on P=':Q syste)s that ha(e an interface to a packet-control
syste) or fireall installed locally for e0a)ple; iptables or TCP #rapper>,
pip is a package )anage)ent syste) used to install and )anage softare packages
ritten in Python,
'ornadois a scalable; non-blockingeb ser(er and eb application fra)eork ritten
in Python,
Tornado is noted for its high perfor)ance, :t tries to sol(e the C17k proble) affecting
other ser(ers, The folloing table shos a bench)ark test of Tornado against other
Python-based ser(ers
'er(er 'etup Reuests per second
Tornado ngin0;four frontends 421&
http://en.wikipedia.org/wiki/Asynchronous_IOhttp://en.wikipedia.org/wiki/Asynchronous_IOhttp://en.wikipedia.org/wiki/Nginxhttp://en.wikipedia.org/wiki/Nginxhttp://en.wikipedia.org/wiki/Asynchronous_IOhttp://en.wikipedia.org/wiki/Nginx -
8/10/2019 Web Development With Python and Flask
10/62
Tornado =ne single-threaded frontend &&&
.Dango Apache)odsgi 222&
eb,py Apache)odsgi 27
CherryPy 'tandalone 34
Chapter 2 - Gettin !our hands dirt! with "#ello $orld%&
()* 'I( *& '+, D-Y: the fastest ay to learn this book is to type e(erything )anually
fro) it, Copy-paste is not producti(e for learning progra))ing unless you understand
177S the code, :f you )ake a typo; then the si)ple action of debugging it ill gi(e you a
reard in learning,
:f you already ha(e a ebser(er and you skipped the first Chapter; run and install the
folloing
sudo apt-get install -y !uild-essential python python-dev python-pip python-mysqld!li!mysqlclient-dev supervisor li!memcached-dev memcached python-memcache
pip install )as% )as%-login )as%-mail sqlalchemy )as%-sqlalchemy )as%-#tf )as%-
migrate tornado )as%-cache simpleencode
pip install pdfminer )as%-admin )as%-security
#ello $orld Application
Create a ne directory under ho)e
cd /home
m%dir hello#orld
create a ne file na)ed run,py
http://en.wikipedia.org/wiki/Django_(web_framework)http://en.wikipedia.org/wiki/Mod_wsgihttp://en.wikipedia.org/wiki/Mod_wsgihttp://en.wikipedia.org/wiki/CherryPyhttp://en.wikipedia.org/wiki/Django_(web_framework)http://en.wikipedia.org/wiki/Mod_wsgihttp://en.wikipedia.org/wiki/CherryPy -
8/10/2019 Web Development With Python and Flask
11/62
nano run.py
run.py
from )as% import *las%app + *las%,__name__
app.route,/
def hello_#orld,"
return 0ello 1orld2
if __name__ ++ __main__"
app.run,
save it /')"0 then 2Y3 ,nter
now type:
python run.py
'hen from your rowser open
http:44your5server5ip:67774
:f you forgot your ser(er ip; rite
wget 89*8 http:44ipecho.net4plain echo
=r if you use digitalocean you can see it after you login on your account after your HP'
na)e,
?ou should see a hite page ith a 2+ello %orld!3, That/s all,
After you are done ad)iring your first flask application; hit CTR9C,
()* 'I( *& '+, D-Y: you can rite on top of run,py U$usrbinpython then ch)od 0run,py so you can Dust type ,run,py instead of !python run,py%,
:f you get error like -bash ,run,py usrbinpythonV+ bad interpreter Ko such file or
directory
apt-get install dos2uni0 then rite !dos2uni0 run,py%, Mand configure your :.E to use 9ine
separator 5ni0 and ='Q, code style-general in :ntelliWN
:f you already kne this; and : offended you ith this ti)e asting info; : apologiIe$
http://127.0.0.1:5000/http://ipecho.net/plainhttp://127.0.0.1:5000/http://ipecho.net/plain -
8/10/2019 Web Development With Python and Flask
12/62
Chapter ' - (ettin up !our develop)ent environ)ent
The settings are Dust )y preferences, ?ou are free to use hate(er you ant of course,
5sing nano to edit scripts is not producti(e, "ere/s a screenshot on ho : do it, ?ou are
free to choose hate(er )ethod suits you hoe(er,
?ou see :ntelliW 'tudio and 'uperPutty,
The te0t is so s)all because : ha(e a 2701**7 resolution best )oney spend e(er ona good )onitor>; : ha(e .E99 5231&"+ no it/s about J77>
: the)ed :ntelliW ith a dark the)e; so )y eyes don/t hurt fro) so )uch hite, ?ou
prefer another color - httpideacolorthe)es,orgho)e they ha(e uite a fe the)es,
Python https,python,orgdonload
:ntelliW 'tudiohttp,Detbrains,co)ideadonload
Putty httpthe,earth,liXsgtatha)puttylatest04putty,e0e
http://ideacolorthemes.org/home/https://www.python.org/downloadhttp://www.jetbrains.com/idea/download/http://www.jetbrains.com/idea/download/http://the.earth.li/~sgtatham/putty/latest/x86/putty.exehttp://ideacolorthemes.org/home/https://www.python.org/downloadhttp://www.jetbrains.com/idea/download/http://the.earth.li/~sgtatham/putty/latest/x86/putty.exe -
8/10/2019 Web Development With Python and Flask
13/62
'uperPutyhttpscode,google,co)psuperputty
'tart :ntelliW; configure hate(er it asks you; choose !Ke ProDect% - Python - don/t
check .Dango; Google App Engine etc> Dust click ne0t, ne0t, Python interpreter, Ka)e
your proDect,
S;ip this step if you plan to use your own computer for development.
-
8/10/2019 Web Development With Python and Flask
14/62
Ko let/s test if e(erything is going ok,
)emove the +ello%orld directory. You are not a eginner anymore :A
9et/s no structure the app a little,Create a ne directory na)ed flasktutorial,
m%dir )as%_tutorial
cd )as%_tutorial
m%dir app
m%dir app/static
m%dir app/templates
:n the )ain directory !flasktutorial% create a file na)ed run,py
:nside app create a55init55.pyand views.py
"ere/s the standard folder structure of a Flask App,
'o e(erything should look like this
)as%_tutorial/
app/
__init__.py
static/
templates/
vie#s.py
run.py
The app folder is containing the bread and butter, 'tatic folder is for css; Ds; Dpg etc, files,
The init,py is here e ill create our app obDect, The run,py is here the ser(er
ill be,
-
8/10/2019 Web Development With Python and Flask
15/62
Edit app455init55.py
from )as% import *las%
3 ene the 1567 application o!$ect
app + *las%,__name__
from app import vie#s
"ere e Dust create the app obDect and i)port the (ies in it, :n (ies e keep all thelogic on ho the app responds to url reuests,
Edit app4run.py
import tornado
from tornado import autoreload
from tornado.#sgi import 15678ontainer
from tornado.httpserver import 099:5erver
from tornado.ioloop import 7;oop
from tornado.log import ena!le_pretty_logging
from app import app
ena!le_pretty_logging,
http_server + 099:5erver,15678ontainer,app
http_server.listen,
ioloop + tornado.ioloop.7;oop,.instance,
autoreload.start,ioloop
ioloop.start,
This is a default configuration on 1 core for the tornado ser(er, #e/ll start like this
because you/ll Dust rite it once and you/ll use it until the end of the book,
-
8/10/2019 Web Development With Python and Flask
16/62
:f you ant to go into details ith tornado; at the end of the book :/ll gi(e you a better
config; but for no this is )ore than enough,
Pretty logging for a nice display on the ter)inal, Kotice that e start the app on port
1BBC$
MofftopicN
If 1BBC doesn=t tell you anything then here=s the wi;ipedia intro to it.
"eetor 1BBC>; also knon as eleetor leetspea;; is an alternati(e alphabetfor the
English languagethat is used pri)arily on the :nternet, :t uses (arious co)binations of
A'C::characters to replace9atinateletters, For e0a)ple; leet spellings of the ord leet
include 1337and l33tY eleet)ay be spelled 31337or 3l33t,
The ter) leet is deri(ed fro) the ord elite, The leet alphabet is a specialiIed for) of
sy)bolicriting, 9eet )ay also be considered a substitution cipher;although )any
dialectsor linguistic (arietiese0ist in different online co))unities, The ter) leetis also
used as an adDecti(eto describe for)idable proess or acco)plish)ent; especially in
the fields of online ga)ingand in its original usage Z co)puter hacking,
MofftopicN
Edit app4views.py
from app import app
app.route,/
app.route,/index
def index,"
http://en.wikipedia.org/wiki/Alphabethttp://en.wikipedia.org/wiki/English_languagehttp://en.wikipedia.org/wiki/Internethttp://en.wikipedia.org/wiki/ASCIIhttp://en.wikipedia.org/wiki/Latin_alphabethttp://en.wikipedia.org/wiki/Latin_alphabethttp://en.wikipedia.org/wiki/Elitehttp://en.wikipedia.org/wiki/Symbolhttp://en.wikipedia.org/wiki/Substitution_cipherhttp://en.wikipedia.org/wiki/Substitution_cipherhttp://en.wikipedia.org/wiki/Dialectshttp://en.wikipedia.org/wiki/Dialectshttp://en.wikipedia.org/wiki/Variety_(linguistics)http://en.wikipedia.org/wiki/Adjectivehttp://en.wikipedia.org/wiki/Adjectivehttp://en.wikipedia.org/wiki/Online_gamehttp://en.wikipedia.org/wiki/Hacker_(hobbyist)http://en.wikipedia.org/wiki/Alphabethttp://en.wikipedia.org/wiki/English_languagehttp://en.wikipedia.org/wiki/Internethttp://en.wikipedia.org/wiki/ASCIIhttp://en.wikipedia.org/wiki/Latin_alphabethttp://en.wikipedia.org/wiki/Elitehttp://en.wikipedia.org/wiki/Symbolhttp://en.wikipedia.org/wiki/Substitution_cipherhttp://en.wikipedia.org/wiki/Dialectshttp://en.wikipedia.org/wiki/Variety_(linguistics)http://en.wikipedia.org/wiki/Adjectivehttp://en.wikipedia.org/wiki/Online_gamehttp://en.wikipedia.org/wiki/Hacker_(hobbyist) -
8/10/2019 Web Development With Python and Flask
17/62
return ?0ello@ 1orld(2?
"ere e )ap the and the inde0 to our !inde0>% function; that Dust returns a si)ple te0t,
Ko go in the )ain folder and run !python run.py
% then ith our broser test the app at
httpyourser(erip1&&3
you should see a !"ello; #orld2$% on it,
Chapter * - +akin the app look ood,
Titter
-
8/10/2019 Web Development With Python and Flask
18/62
Alin% href+?//netdna.!ootstrapcdn.com/!ootstrap/
DD !ootstrap_version GG/css/!ootstrap.min.css? rel+?stylesheet? /
Alin% href+?//netdna.!ootstrapcdn.com/!oots#atch/
DD !oots#atch_version GG/DD !oots#atch_theme GG/!ootstrap.min.css?rel+?stylesheet?
Alin% href+?/static/css/main.css? rel+?stylesheet? /
Alin% rel+?shortcut icon? href+?/static/img/favicon.ico? /
DE !loc% style_!loc% EGD3 page-specic 855 3GDE end!loc% EG
Ascript src+?//cdn$s.cloud)are.com/a$ax/li!s/modernizr/
DD modernizer_version GG/modernizr.min.$s?A/scriptD3 Lodernizr must !e
here@ a!ove !ody tag. 3G
DE !loc% head_script EGD3 defer-incapa!le M5 !loc% 3GDE end!loc% EG
A/head
A!ody
{% include 'includesna!"html' %}D3 pull in nav!ar 3G
Adiv class+?container? id+?maincontent?
{% include 'includesfash#message"html' %}D3 page-level
feed!ac% notices 3G
Adiv id+?!ody_content?
{% block content %}{$ main content area $}{% endblock %}
A/div A/divA2-- /container --
Afooter
Adiv id+?footer? class+?container?
{% block ooter %}{% endblock %}
A/divA2-- /footer --
A/footer
Ascript src+?https"//a$ax.googleapis.com/a$ax/li!s/$query/DD $query_version
GG/$query.min.$s?A/script
Ascript src+?//netdna.!ootstrapcdn.com/!ootstrap/
DD !ootstrap_version GG/$s/!ootstrap.min.$s?A/script Ascript src+?/static/$s/main.$s?A/script
A/!ody
A/html
-
8/10/2019 Web Development With Python and Flask
19/62
(ro tip of the day:instead of the !oots#atch - NslateO theme@ replace it #ith the
one of your li%ing.
?ou notice so)e tags like
{% include 'includesna!"html' %}
As you probably suspect in the te)plates folder create another folder na)ed includes,
#e ill use it to structure our code in a nice ay; adding na(igation to our site )uch
)ore easy,
The variale EE)eans dyna)ic content, 'o)ething like9otal users" &php
total#users( &)in php
4app4templates4includes4nav.html
Anav class+?nav!ar nav!ar-default? role+?navigation?
Adiv class+?nav!ar-header?
A!utton type+?!utton? class+?nav!ar-toggle? data-toggle+?collapse?
data-target+?3!s-example-nav!ar-collapse-
-
8/10/2019 Web Development With Python and Flask
20/62
DE set icon + icon-info-sign EG
DE endif EG
DE for category@ message in messages EG
Adiv class+?alert alert-DD category GG?
Ai class+?DD icon GG?A/i&n!spQ
Aa class+?close? data-dismiss+?alert?RA/a DD message GG
A/div
DE endfor EG
DE endif EG
DE end#ith EG
:n the static folder create = folders" css* img* +s" 7n the folder css create a le
named main"cssand in the $s one main"+s"Bou can use the to add custom
things to your template.
After all this preparation; let/s finally create ourinde$.html
4app4templates4inde$.html
DE extends ?!ase.html? EG
DE !loc% content EG
Adiv style+?font-size"
-
8/10/2019 Web Development With Python and Flask
21/62
from )as% import render_template
import logging
app.route,/
app.route,/indexdef index,"
return render_template,?index.html?
Ko go in the )ain folder and run !python run.py%
8ecause learning so)ething should be fun; let/s uickly test our !ebser(er% to see ho
it perfor)s, :deally you should use another ser(er or )achine for this,
Copy paste so)e rando) loren ipsu) in the inde0,ht)l so you load the page so)e
)ore, [eep in )ind that this is a si)ple static page; no database ueries; no other funny
stuff is inside,
sudo apt-get install apache,-utilsno for the bench)ark rite
a 8n 1777 8c 177 http:44server5ip:1BBC4
9ook at 'ime per re9uest(alue, : get 12,* M)sN )ean> on an i& laptop ith *G8
ra), Try playing ith increasing the -c to 27 for e0a)ple,
(ro tip of the day: This testing is a little useless if you are running the test fro)
localhost and you are not interacting ith any database, ?ou should run it fro) a
different )achine to get )ore accurate results, Also the tornado is set up to use Dust 1
core of your )achine, 8ut this is for the last chapter,
9ater on; e/ll use ngin0 to )ake it e(en faster,
http://server_ip:1337/http://server_ip:1337/ -
8/10/2019 Web Development With Python and Flask
22/62
Chapter - .atabases - )ade si)ple
What well build next:
'@9Alche)y is the Python '@9 toolkit and =bDect Relational +apper that gi(es
application de(elopers the full poer and fle0ibility of '@9,
An =R+ is good for abstracting the datastore slite; )ysl; oracle; etc etc> in order to
pro(ide an interface that can be used in your code,
:f you didn/t installed it fro) the first chapter go ahead and rite
pip install flask-sqlalchemy
8ecause e/ll use lots of configuration constants in our app, 9et/s organiIe the) in a
config file,
-
8/10/2019 Web Development With Python and Flask
23/62
:n the )ain folder flas;5tutorial here the run.pyis> create a ne file called
config.py
4config.py
import os
!asedir + os.path.a!spath,os.path.dirname,__le__
class 8ong,o!$ect"
CTJ6 + *alse
9C597P6 + *alse
5U;K;80CLB_K9KTK5C_JV7 +
K::_PKLC + *las% 9est
5C8VC9_WCB + thisisaveryhardsecret2
-
8/10/2019 Web Development With Python and Flask
24/62
class 9esting8ong,8ong"
5U;K;80CLB_K9KTK5C_JV7 + sqlite"/// X os.path.$oin,!asedir@
d!.sqlite
5U;K;80CLB_L76VK9C_VC: + os.path.$oin,!asedir@ d!_repository 9C597P6 + 9rue
Ko e should let kno that the app ill use this configuration
4app455init55.py
from )as% import *las%
from )as%.ext.sqlalchemy import 5U;Klchemy
import logging
app + *las%,__name__
app.cong.from_o!$ect,cong".e!elopment/ong
d! + 5U;Klchemy,app
logger + logging.get;ogger,__name__
logger.set;evel,logging.7P*
fro) app i)port (ies; )odels
Ko a )odel for the database is reuired; hich are a collection of classes that e/ll use
to interact ith the db,
A dataase modelis a type of data )odel that deter)ines the logical structure of a
database and funda)entally deter)ines in hich )anner data can be stored; organiIed;
-
8/10/2019 Web Development With Python and Flask
25/62
and )anipulated, The )ost popular e0a)ple of a database )odel is the relational
)odel; hich uses a table-based for)at, MikipediaN
create a model.pyin app
4app4model.py
import datetime
from app import d!
class 9rac%ing,d!.Lodel"
__ta!lename__ + ?trac%ing?
id + d!.8olumn,d!.7nteger@ primary_%ey+9rue
user_ip + d!.8olumn,d!.5tring,4Y
user_agent + d!.8olumn,d!.5tring,
-
8/10/2019 Web Development With Python and Flask
26/62
from )as%.ext.admin.contri!.sqla import Lodel[ie#
from app import Z
import logging
F ,$ecutes efore the first re9uest is processed.
Gapp.efore5first5re9uestdef efore5first5re9uest@A:
logging.info@H88888888888888888888 initializing everything 888888888888888888888HA
d.create5all@A
app.route,/
app.route,/index
def index,"
new#tracking 0 Tracking12
new#tracking"add#data1request"remote#addr*request"headers"g
et1'3ser-4gent'22
list#records 0 new#tracking"list#all#users12
or record in list#records5
logging"ino1record"user#ip 6 7 7 6 record"user#agent2
return render_template,?index.html?
/he Gapp.efore5first5re9uest'his creates the dataase when you first access your wesite.
?ou can test the database ith a uick (ie nano db,slite \,you should see your table
there,
5sing re9uest e get the (isitor ip and the user-agent and e store it each ti)e e
refresh the page,
=pen your broserhttpser(erip1&&3
And !python run,py%
?ou should see in the ter)inal so)ething like this
M: 1*7423 112226 (ies14N 162,14,7,12& +oIilla,7 #indos KT ,&Y #=#*>
Apple#eb[it&3,& ["T+9; like Gecko> Chro)e&,7,164,1*& 'afari&3,&
http://server_ip:1337/http://server_ip:1337/http://server_ip:1337/ -
8/10/2019 Web Development With Python and Flask
27/62
and each ti)e you refresh it; )ore records are added,
Chapter 0 - +akin the app tick,
Ko need to rite no; Dust read,
'o the url routing is done like this
app.route,/#elcome
def #elcome,"
return render_template,#elcome.html 3 render a template
This )eans that if you rite you5wesite.com4welcome you ill get the
2welcome.html3fro) the te)plates directory,
?ou can also use the routing to display static content like this
app.route,?/favicon.ico?
def favicon,"
return app.send_static_le,?img/favicon.ico?
or other static contentsee httpstacko(erflo,co)a1*7*7&617&1263
from )as% import *las%@ request@ send_from_directory
app.route,/ro!ots.txt
app.route,/sitemap.xml
def static_from_root,"
return send_from_directory,app.static_folder@ request.path\
-
8/10/2019 Web Development With Python and Flask
28/62
app.route,/post/int5post#id)
def sho#_post,post#id"
3 sho# the post #ith the given id@ the id is an integer
return :ost Ed E post#id
?ou can co)bine the)
8app"route1'hello'2
8app"route1'helloname)'2
def hello,name+Pone"
return render_template,hello.html@ passed#name0name
Kotice the (ariable na)e ith the default Kone, ?ou can use it in your te)plates using ]]
\ ^^
like BpGreeting passed#name EE$Bp
and you can specify http )ethods
_app,route
if re9uest.method K(*S'K:
do5the5login@A
else:
show5the5login5form@A
Ko let/s )odify the inde0,ht)l te)plate to sho nicely the records in our database and
add a ne url to display a record by id,
4app4views.py
from )as% import render_template@ request
from app import Z
from models import Z
app.route,/
app.route,/index
def index,"
ne#_trac%ing + 9rac%ing,
ne#_trac%ing.add_data,request.remote_addr@ request.headers.get,Jser-
-
8/10/2019 Web Development With Python and Flask
29/62
Kgent
list#records 0 new#tracking"list#all#users12
return render_template,?index.html?@ list#records0list#records
()* 'I( *& '+, D-Y:?ou can use /')"0-"'0"to re-for)at your code in :ntelliW, Try
it,
The return Tracking,uery,all> returns a list ith all records, #e passed the list of all
records to our inde0 te)plate,
Quick intro into ina2 3the te)plates that4lask is usin5
read more herehttp:44NinNa.pocoo.org4docs4dev4templates4
for the if we have:
]S if True S^
it/s true
]S endif S^
a for statement is done li;e this
]S for ite) in listofite)s S^
do so)ething ith ]] ite) ^^]S endfor S^
and for if4else:
]S if kenny,sick S^
[enny is sick,
]S elif kenny,dead S^
?ou killed [enny$ ?ou bastard$$$
]S else S^
[enny looks okay --- so far]S endif S^
you can also use else with for li;e this:
Bul
]S for user in users S^
Bli]] user,userna)e ^^Bli
http://jinja.pocoo.org/docs/dev/templates/http://jinja.pocoo.org/docs/dev/templates/http://jinja.pocoo.org/docs/dev/templates/ -
8/10/2019 Web Development With Python and Flask
30/62
]S else S^
BliBe)no users foundBe)Bli
]S endfor S^
Bul
Mgreat e0a)ples taken fro) DinDa2 docu)entationN
so e )odify our inde0,ht)l
4app4templates4inde$.html
]S e0tends base,ht)l S^
]S block content S^
Bdi( styleOfont-siIe 1,e)Yte0t-align center
Bh&Test FlaskBh&
Bhr
O for record in list5records OE
record.user5ip EE
Pr 4Q
record.user5agent EE
O endfor OE
Bdi(
]S endblock content S^
Test it in your broser, #orks$ but ait; it looks ugly, 9et/s rap it up in a bootstrap nice
table,
DE extends ?!ase.html? EG
DE !loc% content EG
Adiv style+?font-size"
-
8/10/2019 Web Development With Python and Flask
31/62
tr)
td) {{ record"user#ip }}td)
td){{ record"user#agent }}td)
tr)
{% endor %}
table) A/div
DE end!loc% content EG
and edit the
4app4static4css4main.css
td D
font-size" F.HemQ
text-align" leftQ
G
Test it, 9ooks )uch better no isn/t it
Goin even 4urther
(rolem if you refresh the page couple of ti)es you get bigger and bigger listing, 9et/s
add pagination to it, #ith '@9Alche)y pagination is piece of cake, "ere/s the recipesince :/) supposing you don/t ha(e ti)e to read the official docu)entation,
:n config,py in the )ain ConfigobDect> add "IS'I#LS5(,)5(-L, 6
class ConfigobDect>
.E85G O False
TE'T:KG O False
'@9A9C"E+?.ATA8A'E5R: O
-
8/10/2019 Web Development With Python and Flask
32/62
4app4views.py
fro) flask i)port renderte)plate; reuest
fro) app i)port L
fro) )odels i)port L
_app,route
-
8/10/2019 Web Development With Python and Flask
33/62
Btable
Pul classHpaginationHQ
O8 for page in list5records.iter5pages@A OE
O if page OE
O if page ! list5records.page OE PliQ Pa hrefH url5for@Kinde$K page pageA EEHQ page EEP4aQ P4liQ
O else OE
Pli classHactiveHQ Pa hrefHFHQPstrongQ page EEP4strongQP4aQ
P4liQ
O endif OE
O else OE
PliQ Pspan classellipsisQRP4spanQ P4liQ
O endif OE
O8 endfor OE
P4ulQ
Bdi(
]S endblock content S^
Test it; and see the greatness of your ork$
M:f so)ething is rong; copy-paste the file fro) the githubN
*ptional Improvements:
add a time formatting:
Btd ]] record,atti)e.strftime@KOY8Om8Od O+:O>:OSKA ^^Btd
order the records y created time:
4app4models.py
\...]
rom sqlalchemy import asc* desc
\...]
def list_all_users,self@page@ ;7597P65_:CV_:K6C"
return
9rac%ing.query"order#by1desc1Tracking"at#time22"paginate,page@
;7597P65_:CV_:K6C@ *alse
-
8/10/2019 Web Development With Python and Flask
34/62
-dd some test data
'ince you/(e been connecting Dust fro) your co)puter; add a ne different record to the
database by accessing it fro) a eb pro0y,
httpssi)ple-pro0y,co)Mnote if you de(elop fro) a local netork you can open the port fro) your routerN
Mnote2 if you don/t like this Dust add so)e du))y test dataN
du))y test dataY
so)ehere in inde0
ne#_user + 9rac%ing,user_ip+O
-
8/10/2019 Web Development With Python and Flask
35/62
and duplicate theinde$.html to trac;5ip.html
Moptional you can )odify it/s title fro) Test Flask to Track :P or so)ethingN
')all instant ho)eork, :f you add )ore test data; you see that the pagination doesn/t
ork, Fi0 it,
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
M------------ spoiler alert ------------N
change the ]]urlfor`inde0/>^^ in the pagination at the botto) to urlfor!trackuserip%>N
Test it http:44server5ip:1BBC4trac;41.11.1.6T
-lternative ith Flask-Restless create an AP: for addingdeletingupdating a record,
Flask-Restless pro(ides si)ple generation of Re'Tful AP:s for database )odels definedusing '@9Alche)y or Flask-'@9Alche)y>, The generated AP:s send and recei(e
)essages in W'=K for)at,
http://server_ip:1337/track/91.121.21.58http://server_ip:1337/track/91.121.21.58 -
8/10/2019 Web Development With Python and Flask
36/62
Chapter 6 - For)s
9et/s create so)e for)s to add ne records to our database,
create a ne file4app4forms.py
4app4forms.py
from app import Z
from #tforms.validators import Vequired@ ;ength
from #tforms import *orm@ 9ext*ield
class 9rac%ing7nfo*orm,*orm"
user_ip + 9ext*ield,user_ip@ validators+\Vequired,@ ;ength,max+4Y@
message+max 4Y characters]
user_agent + 9ext*ield,user_agent@ validators+\;ength,max+4Y@ message+max
4Y characters]
#e are using #TF For)s, ?ou can play ith the) like adding different fields; (alidators, 8ut/s
let/s keep it basic for no,
change the i)ports of app(ies,py to
4app4views.py
i)port logging
fro) flask i)port renderte)plate; reuest; flash
fro) )odels i)port L
from forms import
#e/re i)porting logging to do so)e debuging in the app; the for)s and !flash% to display so)e
feedback to the user,
-
8/10/2019 Web Development With Python and Flask
37/62
and add this to (ies,py
4app4views.py
\...]
app.route,/add_record@ methods+\6C9@ :59]
def add_record,"
form + 9rac%ing7nfo*orm,request.form
if request.method ++ :59"
if form.validate,"
ne#_trac%ing + 9rac%ing,
user_ip + form.user_ip.data
user_agent + form.user_agent.data logging.info,?adding ? X user_ip X ? ? X user_agent
ne#_trac%ing.add_data,user_ip@ user_agent
)ash,?added successfully?@ category+?success?
return render_template,?add_record.html?@ form+form
5pdate the na(igation bar
4app4templates4includes4nav.html
Bna( classOna(bar na(bar-default roleOna(igation
Bdi( classOna(bar-header
Bbutton typeObutton classOna(bar-toggle data-toggleOcollapse data-targetOUbs-
e0a)ple-na(bar-collapse-1
Bspan classOsr-onlyToggle na(igationBspan
Bspan classOicon-barBspan
-
8/10/2019 Web Development With Python and Flask
38/62
Bspan classOicon-barBspan
Bspan classOicon-barBspan
Bbutton
Ba classOna(bar-brand hrefOTest FlaskBa
Bul classOna( na(bar-na( na(bar-right
PliQPa hrefH4add5recordHQ-dd recordP4aQP4liQ
Bul
Bdi(
Bna(
Test it by adding fe records to the db,You should also see in the terminal the deug
message.
The )ost i)portant part of this chapter are 2 ho)eorks that you really should do, They are
si)ple and should take 2-& )inutes for the first one and about 17 )inutes for the second,
#o)ework 1,
-dd a validator for ip address in the form.
+I#': You should search the documentation of %'&&orms
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
-
8/10/2019 Web Development With Python and Flask
39/62
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
fro) tfor)s,(alidators i)port Reuired; 9ength;I(-ddress
userip O Te0tField
#o)ework 2,
Re)e)ber the trac;5user5ip to display a record filtered by ip Add to the trac;5ip.html page a
for) ith one input te0t here you can enter the :P and a button sub)it, .isplay the filtered ip
-
8/10/2019 Web Development With Python and Flask
40/62
page after,
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
M spoiler alert N
add
4app4forms.py
class Uueryne*orm,*orm"
user_ip + 9ext*ield,user_ip@ validators+\Vequired,@ 7:Kddress,message+?7nvalid
7: Kddress?]
4app4templates4includes4nav.html
BliBa hrefOtrack@uery recordBaBli
-
8/10/2019 Web Development With Python and Flask
41/62
4app4views.py
modify trac;5user5ip function to:
app.route,/trac%@ methods+\6C9@ :59]
app.route,/trac%/Auser_ip@ methods+\6C9@ :59]
app.route,/trac%/Auser_ip/Aint"page@ methods+\6C9@ :59]
def trac%_user_ip,user_ip+??@ page+
-
8/10/2019 Web Development With Python and Flask
42/62
di! class07row7)
di! class07well bs-component7)
orm class07orm-hori=ontal7 method07post7 action077)
eldset)
legend)>earch by 9:legend)
di! class07orm-group7)
label or07user#ip7 class07col-lg-? control-label7)3ser
9:label)
di! class07col-lg-@7)
{{orm"user#ip 1class07orm-control72}}
{% or error in orm"errors"user#ip %} br)
di! class07alert alert-danger7 style07display5
inline-block7)
{{error}}
di!)
{% endor %}
di!)
di!)
di! class07orm-group7)
di! class07col-lg-? col-lg-oAset-?7)
-
8/10/2019 Web Development With Python and Flask
43/62
button type07submit7 class07btn btn-
primary7)>earchbutton)
di!)
di!)
eldset)
orm)
di!)
Ata!le class+?ta!le ta!le-striped ta!le-!ordered ta!le-hover?
Athead
Atr
AthKt 9imeA/th
Ath7:A/th
AthJser KgentA/th
A/tr
A/thead
DE for record in list_records.items EG
Atr
Atd DD record.at_time.strftime,EB-Em-Ed E0"EL"E5 GGA/td
Atd DD record.user_ip GGA/td
-
8/10/2019 Web Development With Python and Flask
44/62
AtdDD record.user_agent GGA/td
A/tr
DE endfor EG
A/ta!le
Aul class+?pagination?
DE- for page in list_records.iter_pages, EG
DE if page EG
DE if page 2+ list_records.page EG
Ali Aa href+?DD url_for,'track#user#ip'@ user#ip 0 user#ip@ page +
page GG?DD page GGA/a A/li
DE else EG
Ali class+?active? Aa
href+?3?AstrongDD page GGA/strongA/a A/li
DE endif EG
DE else EG
Ali Aspan class+ellipsis^A/span A/li
DE endif EG
DE- endfor EG
A/ul
A/div
DE end!loc% content EG
-
8/10/2019 Web Development With Python and Flask
45/62
Chapter 7 - 8ser loin - with )anae)ent
To rite yourself the user registration; e)ail confir)ation; forgot passord etc, ould
take so)e ti)e and you/d ha(e to be (ery good to rite it ithout bugs and opti)iIed,
#e are grateful for ha(ing &las;8Securityto sa(e our souls,
httpspythonhosted,orgFlask-'ecurityinde0,ht)l
9et/s get our hands dirty, #e ant a user register; confir)ation by e)ail; forgot
passord and a secretpage ith a ultra-secret infor)ation inside,
#e/ll use yahoo; that has a li)it of 177 e)ails per day, For our testing purposes it ill be
ok,
:f you ha(e another )ail ser(er; Dust change the config,
For large (olu)es you can check httpsendgrid,co)
9et/s clear our pre(ious database first,
rm 8rf d.s9lite
To use &las;8Security; first let/s configure it
add this (alues in the )ain Config
4config.py
5C8JV79B_VC6759CVKT;C + 9rue
5C8JV79B_VC8[CVKT;C + 9rue 5C8JV79B_9VK8WKT;C + 9rue
5C8JV79B_:K551V_0K50 + shaS
-
8/10/2019 Web Development With Python and Flask
46/62
LK7;_J5C_9;5 + *alse
LK7;_J5CVPKLC + emailyahoo.com
LK7;_:K551V + pass#ord
C*KJ;9_LK7;_5CPCV + emailyahoo.com
5C8JV79B_CLK7;_5CPCV + emailyahoo.com
e need to add the flask-)ail obDect
4app455init55.py
M,,,N
fro) flask)ail i)port +ail
M,,,N
)ail O +ailapp>
#e need to update our )odels,py too
4models.py
from )as%.ext.security import JserLixin@ VoleLixin@
5U;KlchemyJseratastore
roles_users + d!.9a!le,roles_users@
d!.8olumn,user_id@ d!.7nteger,@ d!.*oreignWey,user.id@
d!.8olumn,role_id@ d!.7nteger,@ d!.*oreignWey,role.id
class Jser,d!.Lodel@ JserLixin"
id + d!.8olumn,d!.7nteger@ primary_%ey+9rue
email + d!.8olumn,d!.5tring,(SS@ unique+9rue
pass#ord + d!.8olumn,d!.5tring,(SS
active + d!.8olumn,d!.Toolean,
conrmed_at + d!.8olumn,d!.ate9ime,
roles + d!.relationship,Vole@ secondary+roles_users@
!ac%ref+d!.!ac%ref,users@ lazy+dynamic
last_login_at + d!.8olumn,d!.ate9ime,
current_login_at + d!.8olumn,d!.ate9ime,
last_login_ip + d!.8olumn,d!.5tring,(SS
current_login_ip + d!.8olumn,d!.5tring,(SS
login_count + d!.8olumn,d!.7nteger
def __repr__,self"
return Amodels.Jser\email+Es] E self.email
-
8/10/2019 Web Development With Python and Flask
47/62
class Vole,d!.Lodel@ VoleLixin"
id + d!.8olumn,d!.7nteger,@ primary_%ey+9rue
name + d!.8olumn,d!.5tring,HF@ unique+9rue
description + d!.8olumn,d!.5tring,(SS
user_datastore + 5U;KlchemyJseratastore,d!@ Jser@ Vole
And the (ies,py
4views.py
\...]
from )as%.ext.security import 5ecurity@ login_required@ logout_user
\...]
security + 5ecurity,app@ user_datastore
app.route,/secret
login_required
def secret,"
return render_template,secret.html
no create a si)ple secret.htmlin te)plates and rite !secret page% in the content,
&las;8securityuses so)e te)plates, 8ecause They are si)ple; and self e0planatory; :
on/t copy paste the) here,
:/(e custo)iIed )y on te)plates ith bootstrap; also you/ll find e)ail te)plates,
"ere is the all chapter ith all the code, ?ou Dust ha(e to edit the config fileith your
mail credentials,
httpsgithub,co)Andrei.Flask8ooktree)asterflaskbookchapter4
Chapter 9 - An Ad)in Panel to save us all
&las;8-dmin
pip install &las;8-dmin
https://github.com/AndreiD/FlaskBook/tree/master/flask_book/chapter_8https://github.com/AndreiD/FlaskBook/tree/master/flask_book/chapter_8 -
8/10/2019 Web Development With Python and Flask
48/62
httpsgithub,co))rDoesflask-ad)in
Flask-Ad)in is a batteries-included; si)ple-to-use Flaske0tension that lets you add
ad)in interfaces to Flask applications, :t is inspired by the dDango-ad)in package; but
i)ple)ented in such a ay that the de(eloper has total control of the look; feel and
functionality of the resulting application, official description>
#orking ith flask ad)in is (ery si)ple, "ere/s the ay to do it ith '@9Alche)y,
from )as%.ext.admin.contri!.sqla import Lodel[ie#
3 *las% and *las%-5U;Klchemy initialization here
admin + Kdmin,app
admin.add_vie#,Lodel[ie#,Jser@ d!.session
And this is all$ :t creates an ad)in panel for the 5ser; ith all the goodies that co)e ith
it,
"oe(er; e ant to custo)iIe it and to protect it with flas;8security.
from )as%.ext.admin.contri!.sqla import Lodel[ie#
3 *las% and *las%-5U;Klchemy initialization here
class Ly[ie#,Lodel[ie#" 3 isa!le model creation
can_create + *alse
3 verride displayed elds
column_list + ,login@ email
def __init__,self@ session@ ZZ%#args"
3 Bou can pass name and other parameters if you #ant to
super,Ly[ie#@ self.__init__,Jser@ session@ ZZ%#args
admin + Kdmin,app
admin.add_vie#,Ly[ie#,d!.session
To the +yHie class e can add
def is_accessi!le,self"
https://github.com/mrjoes/flask-adminhttp://flask.pocoo.org/https://github.com/mrjoes/flask-adminhttp://flask.pocoo.org/ -
8/10/2019 Web Development With Python and Flask
49/62
return current_user.has_role,admin
'o here/s the code for our app, There/s no need to copy it; Dust read it line by line and try
to understand it
3 -------------------------- KL7P :KV9 ------------------------------------
class Ly[ie#,Tase[ie#"
expose,/
def index,self"
return self.render,admin/index.html
class 9rac%ingKdmin[ie#,Lodel[ie#"
can_create + 9rue
de is#accessible1sel25
return current#user"has#role1'end-user'2
def __init__,self@ session@ ZZ%#args"
super,9rac%ingKdmin[ie#@ self.__init__,9rac%ing@ session@ ZZ%#args
class JserKdmin[ie#,Lodel[ie#"
column_exclude_list + ,pass#ord
de is#accessible1sel25
return current#user"has#role1'admin'2
def __init__,self@ session@ ZZ%#args"
super,JserKdmin[ie#@ self.__init__,Jser@ session@ ZZ%#args
class Vole[ie#,Lodel[ie#"
def is_accessi!le,self"
return current_user.has_role,admin
def __init__,self@ session@ ZZ%#args"
super,Vole[ie#@ self.__init__,Vole@ session@ ZZ%#args
admin + Kdmin,app@ name+?*las% 9est Kdmin?
admin.add_vie#,9rac%ingKdmin[ie#,d!.session
admin.add_vie#,JserKdmin[ie#,d!.session
admin.add_vie#,Vole[ie#,d!.session
-
8/10/2019 Web Development With Python and Flask
50/62
3 -------------------------- KL7P :KV9 CP ---------------------------------
Chapter 1: - Prepare 4or the production environ)ent
Ti)e has co)e to let the orld kno on hat e/(e been spending our resources,,,especially
ti)e,
8efore e (enture into spending JJJ into ad(ertising it > let/s )ake sure the production release is
good,
E(erything : kno; : share it ith you, :f any of you are )ore knoledgeable than )e and you
ant to share this ith the people that ill read this book; please e)ail )e your suggestions
using the httpandroidad(ance,co)contact for),
#hat e plan to do
Ti)e to lea(e slite and )o(e to )ysl,
:f by so)e )ysterious force our app breaks; e ant to restart auto)atically
9et/s ser(e the app fro) ngin0 ith a )odified tornado
;n order to tune the app 4or per4or)ance< lets 4irst )ake it do so)e hard work, Go into con4i
and )odi4! the LISTI!S"P#$"P%!# & '((
=ow 4or the testin lets use apache bench)ark, /he idea is to use it 4ro) a di44erent )achine
than the one !ou are hostin the app, ;4 !ou have 2 servers ust use another one< i4 !ou want to
have it on windows
Go to http>??www,apachehaus,co)?ci-bin?download,pl@and download -pache .V.17 $WV @you
have a $WV *S don=t you XA. Inside 4in you find a.e$e. )un it with (owerShell or cmd Nust li;e on linu$
'esting with:
.a.e$e 8n 177 8c 67http:44server5ip:1BBC4 @replace .a.e$e with a in linu$A
n an old i' laptop< *GB RA+< with a shitt! #..
http://androidadvance.com/http://www.apachehaus.com/cgi-bin/download.plxhttp://www.apachehaus.com/cgi-bin/download.plxhttp://server_ip:1337/http://server_ip:1337/http://androidadvance.com/http://www.apachehaus.com/cgi-bin/download.plxhttp://server_ip:1337/ -
8/10/2019 Web Development With Python and Flask
51/62
?run,p!
http_server + 099:5erver,15678ontainer,app
http_server.listen,
ioloop + tornado.ioloop.7;oop,.instance,
autoreload.start,ioloop
ioloop.start,
$ell call it sinle threaded< 1 core,
Testing on single core* sqlite database
Vequests per second" B"CD\3/sec] ,mean
9ime per request" H4S.4> \ms] ,mean
9ime per request"
Ti)e per reuest 3*,377 M)sN )ean; across all concurrent reuests>
-
8/10/2019 Web Development With Python and Flask
52/62
Alright; no e/re talking, #ith )ultithread and )ysl the perfor)ance skyrocketed,
Jsudo apt-get install ngin0
ngin0 * core tornado )ysl
Reuests per second 1B.V6MUsecN )ean>
Ti)e per reuest &31,4* M)sN )ean>Ti)e per reuest 3*,&&3 M)sN )ean; across all concurrent reuests>
+ow to configure ngin$ with flas;.
/lean and install ngin$ if you already played with it.
sudo apt-get purge nginx nginx-common nginx-full
then reinstall
sudo apt-get install nginx
Test if ngin0 is running, =pen the ip of your ser(er, ?ou should see a !hello orld fro)
ngin0% )essage,
Read this article https,digitalocean,co)co))unitytutorialsho-to-opti)iIe-
ngin0-configuration
MKote all config files are in httpsgithub,co)Andrei.Flask8ooklast chapterN
no let/s put flask in ngin0
4etc4ngin$4sites8enaled4default
server D
listen HF defaultQ
server_name domain.comQ
server_name ###.domain.comQ
access_log /var/log/nginx/domain.com.access.logQ
root /home/your_)as%_pro$ectQ
location /static/ D
expires maxQ
add_header ;ast-Lodied `sent_http_CxpiresQ
alias /home/your_)as%_pro$ect/app/static/Q
https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configurationhttps://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configurationhttps://github.com/AndreiD/FlaskBookhttp://www.domain.com/https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configurationhttps://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configurationhttps://github.com/AndreiD/FlaskBookhttp://www.domain.com/ -
8/10/2019 Web Development With Python and Flask
53/62
G
location / D
try_les `uri tornadoQ
G
location tornado D
proxy_set_header 0ost `hostQ
proxy_set_header I-Veal-7: `remote_addrQ
proxy_set_header I-*or#arded-*or `proxy_add_x_for#arded_forQ
proxy_pass http"//.F.F.
-
8/10/2019 Web Development With Python and Flask
54/62
language can use to )onitor it; and an Q+9-RPC interface for control, :t is also built ith
e0tension points that can be le(eraged by Python de(elopers,
Co)patible
'uper(isor orks on Dust about e(erything e0cept for #indos, :t is tested and
supported on 9inu0; +ac =' Q; 'olaris; and Free8'., :t is ritten entirely in Python; so
installation does not reuire a C co)piler,Pro(en
#hile 'uper(isor is (ery acti(ely de(eloped today; it is not ne softare, 'uper(isor has
been around for years and is already in use on )any ser(ers,
#ote that: Supervisor will not run at all under any version of %indows.
let/s no insert our progra) into super(isor, Ter)inate the app if you ha(e it running and
4etc4supervisor4supervisord.conf
Q supervisor cong le
\unix_http_server]
le+/var/run/supervisor.soc% Q ,the path to the soc%et le
chmod+F>FF Q soc%ef le mode ,default F>FF
\supervisord]
logle+/var/log/supervisor/supervisord.log Q ,main log leQdefault
`81/supervisord.log
logle_max!ytes+SFLTpidle+/var/run/supervisord.pid Q ,supervisord pidleQdefault supervisord.pid
childlogdir+/var/log/supervisor Q ,KJ9 child log dir@ default `9CL:
Q the !elo# section must remain in the cong le for V:8
Q ,supervisorctl/#e! interface to #or%@ additional interfaces may !e
Q added !y dening them in separate rpcinterface" sections
\rpcinterface"supervisor]
supervisor.rpcinterface_factory +
supervisor.rpcinterface"ma%e_main_rpcinterface
\supervisorctl]
serverurl+unix"///var/run/supervisor.soc% Q use a unix"// JV; for a unix soc%et
Q 9he \include] section can $ust contain the ?les? setting. 9his
Q setting can list multiple les ,separated !y #hitespace or
Q ne#lines. 7t can also contain #ildcards. 9he lenames are
Q interpreted as relative to this le. 7ncluded les ZcannotZ
Q include les themselves.
-
8/10/2019 Web Development With Python and Flask
55/62
\include]
les + /etc/supervisor/conf.d/Z.conf
Eprogram5mysuperappcommand0python homethe#path#to#your#pro+ectrun"py
stderr#logle 0 !arlogsuper!isormysuperapp-stderr"log
stdout#logle 0 !arlogsuper!isormysuperapp-stdout"log
autostart0true
autorestart0true
stdout#logle#maGbytes0HIJK
stderr#logle#maGbytes0HIJK
startsecs0B
startretries0,I
7f you #ant@ you can read more a!out supervisor cong at
http"//supervisord.org/conguration.html
You have so many users that your server can=t hold them X
find out here/s the bottleneck
check Flask-Cache for a nice ay to i)ple)ent caching in your app
split the logic into )ultiple ser(ers
ask for help on stacko(erflo,co)
see http,)a0cdn,co)
)oney are no proble) Get a *G8 27 CP5' *7G8 ''. .:'[ 6T8
TRAK'FER +=KT"9? J*7,77 fro) digitalocean,,,or 2; &\
Chapter 11 - Goin online
>y >ethod!
#hen it co)es to buying do)ain na)es : go ith na)echeaphttp,na)echeap,co)affO*73please use the link if you ant to say thanks for
this book>
1, 8uy a do)ain fro) na)echeap,
2, Get a HP' fro) digitalocean,co) httpgoo,glAr9(y0 )y referal link again and you
get J17 on your account after you )ake it>
&, Ko in your na)echeap do)ain )anager
+y Account+anage .o)ains+odify .o)ain
http://supervisord.org/configuration.htmlhttp://www.maxcdn.com/http://www.namecheap.com/?aff=64507http://goo.gl/ArLvyxhttp://goo.gl/ArLvyxhttps://manage.www.namecheap.com/myaccount/index.asphttps://manage.www.namecheap.com/myaccount/domain-list.asphttp://supervisord.org/configuration.htmlhttp://www.maxcdn.com/http://www.namecheap.com/?aff=64507http://goo.gl/ArLvyxhttps://manage.www.namecheap.com/myaccount/index.asphttps://manage.www.namecheap.com/myaccount/domain-list.asp -
8/10/2019 Web Development With Python and Flask
56/62
'pecify Custo) .K' 'er(ers ?our on .K' 'er(ers >
K'1,.:G:TA9=CEAK,C=+
K'2,.:G:TA9=CEAK,C=+
K'&,.:G:TA9=CEAK,C=+
*, Ko go to your digitalocean,co) dashboardcreate a ne droplet hile the )ini)u) droplet should be enough for start; get the
1GhI one if J per )onth is not too )uch for you>
Click the droplet,
Go to .K'
Fro) the top button click !Add .o)ain%
'elect the droplet fro) the left, The :P address should be added auto)atically
Enter the do)ain na)e E0 androidad(ance,co)>
Add an !A% record \ pointing to the droplet ip
_ \\\\\\\,, ipofthedroplet
Jthis might e already added for youM
Add a CKA+E
L,,,,,,,,,,,,,,,,,,,,,,,,,,,,, _
MoptionalN Add CKA+Es for a subdo)ainsubdo)ain,do)ain,co)\\\\\\\\\\,_
,$ample:
-
8/10/2019 Web Development With Python and Flask
57/62
Ko login in your droplet; install super(isor; install ngin0; deploy your super flask app
etc,
-
8/10/2019 Web Development With Python and Flask
58/62
Chapter 1 - A list o4 addons that )iht interest !ou
s;ipping the ones that we already used.
&las;8
-
8/10/2019 Web Development With Python and Flask
59/62
1, create a folder called utils, inside it create an e)pty file called init,py
this is called a package, and the init,py tells python that there are )odules to be
i)ported fro) this folder,
2, create colorstrea)handler,py
Google mooware 4 colorstreamhandler.py and copy-pate it fro) his gist.
Msidenote Gist is a si)ple ay to share snippets and pastes ith others, All gists are Git
repositories; so they are auto)atically (ersioned; forkable and usable fro) Git, ?ou can
create to kinds of gists public and pri(ate,
&, create generalutils,py
3 -Z- coding" utf-H -Z-
import logging
import logging.handlers
import colorstreamhandler
;6_*7;CPKLC + ../;8K97P/the_log.out
my_logger + logging.get;ogger,Ly;ogger
my_logger.set;evel,logging.CTJ6
le_handler + logging.handlers.Votating*ile0andler,;6_*7;CPKLC@
maxTytes+
-
8/10/2019 Web Development With Python and Flask
60/62
if category ++ ?error?"
my_logger.error,message
\edit the ;8K97P for ?the_log.out?]
3 -Z- coding" utf-H -Z-? is good if you #or% #ith russian@chineese characters.
?;6_*7;CPKLC + ../folder/the_log.out? si #here the_log.out #ill !e
Votating*ile0andler #ill %eep it small...so you dont end up #ith (FF6T log
les.
le_handler.set;evel,logging.CVVV - #e only log CVVV5 to the le
no# #e add another handler and set the logging level to P95C9 so #e see
everything in the console.
Po# #e call our log #ith"
/some_le.py
32/usr/!in/python
3-Z- coding" utf-H -Z-from utils import general_utils
general_utils.cool_log,?hello from error?@?error?
general_utils.cool_log,?hello from de!ug?@?de!ug?
you should see !oth messages displayed in color on your console. and $ust
the error message logged to le.
0ome#or%"
add time to the log in the le ,hint" use ?EB-Em-Ed E0"EL"E5? and level
name in the console display.
-
8/10/2019 Web Development With Python and Flask
61/62
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
\------ spoiler alert ----------]
le_handler.set*ormatter,logging.*ormatter,?E,asctimes 333 E
,messages?@ ?EB-Em-Ed E0"EL"E5?
stderr_log_handler.set*ormatter,logging.*ormatter,?E,levelnames 333 E
,messages?@ ?EB-Em-Ed E0"EL"E5?
-
8/10/2019 Web Development With Python and Flask
62/62
Kfter you logged in to #e!min@ lets congure it to !e a!le to send us
notication mails.
1e!min 8onguration 5ending Cmail ,on the !ottom of the screen
8ongure ?5end email using?
Pote" 7 use sendgrid@ so 7 put [ia 5L9: to remote mail server
smtp.sendgrid.net port SH> and my username and pass#ord@ 5L9:
authentication method" ?;ogin?. Tut if you prefer another setting please
congure it.
ne of the most important things to do is !ac%up the data!ase. 0eres ho#"
pen Ly5U; ata!ase 5erver on servers ,or in unused modules
enter root and pass#ord
on the !ottom you have ?!ac%up data!ases? #ith all the nice options@
including 5cheduled !ac%up ena!led and sending mail in case the !ac%up
fails. 5#eet
:ro!lem. 7f you chose to ma%e !ac%up every day@ the #e!min over#rites the
les. 1e #ant to create a ne# folder everytime a !ac%up is done.
9o ena!le this return to the main mysql server module. 8lic% module cong
lin% ,upper part. 5et o strftime su!stitution of !ac%up destinationsb BC5
Po# in the !ac%up data!ase screen #rite the !ac%up folder #ith/home/!ac%ups/Ed-Em-EB/ ,example if you #ant daily !ac%ups. Po# each
time a !ac%up is done@ it #ill create a ne# folder.
Pote" in case your data!ase is a !ig one@ you might #ant to consider other
methods.
0ome#or%"
1e!min has lots of other cool things too. 8hec% ta! ?*ilesystem Tac%up? and
?5cheduled 8ron Mo!s?