Top Banner

of 62

Web Development With Python and Flask

Jun 02, 2018

Download

Documents

danandreist
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • 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?