Web Development With Python and Flask

download Web Development With Python and Flask

of 62

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?