KEMBAR78
LvivPy - Flask in details | KEY
Flask in details
           Max Klymyshyn
        CTO at GVMahines

          @maxmaxmaxmax
            github: joymax
From Django to Flask

    and back to Django
I remember when Flask appeared

And I was one of guys who hadn't
         read the code
  when Flask was just a joke.
But Armin is
really nice,
simple and
very smart guy
And when I start worked with Flask,
              aam...
Now I feel like ...
NA NA NA
Devil is in the details
Here is details
1. Typical project structure
2. Blueprints
3. Database
4. Forms & Validation
5. Management Commands
6. Assets-management
7. Replacement of django.contrib.admin
8. Debugging
9. Unit tests and Behavior tests
Project structure
1. pure python module:

 settings.py
 - project
   - app.py
   - views.py
   - templates
   - static
   ...

2. Configuration: local_settings, settings:

app.config.from_object(settings)
Blueprints
Kind of django-apps
1. Initialization:
from flask import Blueprint
app = Blueprint(
       'profile', // namespace
       __name__, // logical python module or
                   // package
       template_folder='templates',
       static_folder='static'
       )
...
@app.route('/sample/')
def sample():
       ...
Register blueprint
1. To register use app.register_blueprint :
      from flask import Flask
      from proj.submodule.bp import app as
submodule

      app = Flask(__name__)
      app.register_blueprint(
          submodule,
          url_prefix='/submodule'
      )
2. Url namespace
{{ url_for('profile.sample') }}
Database
Flask-SQLAlchemy
    minimongo
    Flask-Redis
Flask-SQLAlchemy
Example configuration from docs:

from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 
    'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
Flask-SQLAlchemy
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(
        db.String(80), unique=True)
    email = db.Column(
        db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username
Flask-SQLAlchemy
>>> from app import db
>>> db.create_all()
>>> from app import User
>>> admin = User('admin', 'admin@example.com')
>>> guest = User('guest', 'guest@example.com')
>>> db.session.add(admin)
>>> db.session.add(guest)
>>> db.session.commit()
>>> User.query.all()
[<User u'admin'>, <User u'guest'>]
Minimongo
 1. No initial configuration needed
 2. Install & start mongo - that's enough
Sample model:

import minimongo as mm

class Profile(mm.Model):
    class Meta:
        database = "sampleproject"
        collection = "profiles"

           indices = (mm.Index('username'))
Minimongo
>>> from app import db, User, Profile
>>> admin = User.query.filter_by(
... username='admin').first()
>>> admin.username
u'admin'
>>> profile = Profile(username=admin.username,
... description=u'Flask devleoper')
>>> profile
{'username': u'admin', 'description': u'Flask
devleoper'}
>>> profile.save()
{'username': u'admin', '_id':
ObjectId('4f13e019486dd09335000001'), 'description':
u'Flask devleoper'}
Minimongo
>>> Profile.collection
Collection(Database(Connection('localhost',
27017), u'sampleproject'), u'profiles')

>>> Profile.collection.find_one(
... {'username': admin.username})
{u'username': u'admin', u'_id':
ObjectId('4f13df60486dd09335000000'),
u'description': u'Flask devleoper'}
Flask-Redis
1. Install flask-redis
2. Add to app.py:
from flask.ext.redis import init_redis
...
redis = init_redis(app)
2. Quite easy to use:
>>> from app import redis
>>> p = redis.pipeline()
>>> p.set("username", "admin")
<redis.client.Pipeline object at 0x10139b350>
>>> p.execute()
[True]
>>> redis.get("username")
'admin'
Forms & Validation

     Flask-WTF
WTForms Form and View
from flask.ext import wtf

class UserForm(wtf.Form):
    username = wtf.TextField("Username", [wtf.Required()])
    email = wtf.TextField(
        "Email", [wtf.Required(), wtf.Email()])

@app.route('/form', methods=['POST', 'GET'])
def form():
    form = UserForm()
    if form.validate_on_submit():
        flash("Success")
        return redirect("/form")
    return render_template("form.html", form=form)
WTForm Template
{% with messages = get_flashed_messages() %}
    {{ ", ".join(messages or []) }}
{% endwith %}
<hr />

<form method="post" action="/form">{{ form.csrf }}
    <i>{{ "; ".join(form.username.errors) }}</i>
    <br />
    {{ form.username(size=20) }}
    <hr />
    {{ "; ".join(form.email.errors) }}<br />
    {{ form.email(size=20) }}
    <hr />
    <input type="submit" value="Go">
</form>
Management Commands

Write external scripts with current
         project context
Flask-Script
1. Create manage.py script within your project directory and put
(which is quite similar to Django's manage.py):

from flaskext.script import Manager
from app import app

manager = Manager(app)

@manager.command
def hello():
    print "hello"

if __name__ == "__main__":
    manager.run()
Flask-Script
maxk$ python manage.py
  shell      Runs a Python shell inside
Flask application context.
  hello
  runserver Runs the Flask development
server i.e. app.run()

maxk$ python manage.py hello
hello
Flask-Script
With Flask-Script you able to:

•   Write custom management commands
•   Use existing ones like in flask-assets
•   Getting user's input
•   Use command line options

All of abilities above already automated with Flask-Script and
it's really easy-to-use.
Assets Management

Static, CSS & JavaScript files
JS/CSS minification and so on
Flask-Assets based on Webassets. To integrate we
need some work to do:

1. Install Flask-Assets
2. Initialize Flask-Assets environment
3. Add Assets Bundles
4. Configure compressors/minifiers etc. to optimize
   our assets
5. Generate bundles with management command
Flask-Assets: initializing environment
import Flask
from flask.ext.assets import Environment as
AssetsEnvironment

app = Flask(__name__)
assets = AssetsEnvironment(app)
assets.debug = True

app.config['ASSETS_DEBUG'] = True

app.config['YUI_COMPRESSOR_PATH'] = 'contrib/
yuicompressor-2.4.6.jar'
Flask-Assets: Adding files
I will show work with JavaScript only but feel free to use same
approach with CSS files.
JavaScript files directory structure:

 - static
   - js
- src
- core
* jquery.js
* underscore.js
- app
* module1.js
* module2.js
Flask-Assets: adding bundles
assets.py:

from flaskext.assets import Bundle

def register_assets(assets):
    core = Bundle(
        'js/src/core/jquery.js',
        'js/src/core/underscore.js',
        filters='yui_js',
        output='js/bundle/core.js'
    )
    assets.register('core', core)
Flask-Assets: adding bundles
...
app = Bundle(
    'js/src/app/*.js',
    filters='yui_js',
    output='js/bundle/app.js'
)

assets.register('app', app)
Flask-Assets: how to use
Somewhere in your template code:

{% assets "core" %}
    <script src="{{ ASSET_URL }}"></script>
{% endassets %}

{% assets "app" %}
    <script src="{{ ASSET_URL }}"></script>
{% endassets %}
Flask-Assets: debug mode
Flask-Assets generate code below (debug mode):
<script src="/static/js/src/core/jquery.js"></
script>
<script src="/static/js/src/core/underscore.js"></
script>

<script src="/static/js/src/app/module1.js"></
script>
<script src="/static/js/src/app/module2.js"></
script>
Flask-Assets: production mode
Flask-Assets generate code below (production mode):

<script src="/static/js/bundles/core.js"></script>
<script src="/static/js/bundles/app.js"></script>

Static files was generated with Flask-Script command:

maxk$ python manage.py assets rebuild
More extensions:
    Flask-Mail
     Flask-Babel
     Flask-Cache
      Flask-csrf
   Flask-FlatPages
    Flask-lesscss
          ...
Admin panel

 Flask-Admin
 Flask-Dashed
Tests

Unit, Behavior and JavaScript tests
Testing: Unit & Behavior
To test templates, views etc we need to have request context

Before execution:

self.app.test_request_context().push()

After execution:

self.app.test_request_context().pop()
Behavior Testes with Lettuce
Example feature and scenario:

Feature: Auth
     Scenario: Sign In as featured expert
            When I go to "auth.login" view
            Then I see that response code is 200
           And There's form with following fields:
                   | form__username |
                   | form__password |
            Fill the field "form__username" with "featured"
lettuce-web
Lettuce-web is a library which very close to headless testing
using twill. lettuce-web doesn't require browser. You can
write your features using lettuce-web predefined steps.



                       More here:
        https://github.com/joymax/lettuce-web
Flask-Jasmine
Flask-Jasmine is extension to execute Jasmine JavaScript
Tests



                       More details
        https://github.com/joymax/flask-jasmine
Debugging

Flask-DebugToolbar
werkzeug debugger
Issues

What's going on in Flask world at
          the moment?
Python 3
Status of porting Flask to Python 3 is unknown.

Werkzeug not ported yet. Hopefully, will be ported to Python
3.3 ( PEP 414 for details)
Werkzeug
Werkzeug is really huge and have tons of tools.
Flask based on Werkzeug.

We all like Python for small, robust and clean libraries.
What’s next?




Flask 0.9
                52
That's all
                  Questions?


                    Source: 
https://github.com/joymax/kyivpy-flask-in-details
LvivPy - Flask in details

LvivPy - Flask in details

  • 1.
    Flask in details Max Klymyshyn CTO at GVMahines @maxmaxmaxmax github: joymax
  • 2.
    From Django toFlask and back to Django
  • 3.
    I remember whenFlask appeared And I was one of guys who hadn't read the code when Flask was just a joke.
  • 5.
    But Armin is reallynice, simple and very smart guy
  • 6.
    And when Istart worked with Flask, aam...
  • 8.
    Now I feellike ...
  • 9.
  • 10.
    Devil is inthe details
  • 11.
    Here is details 1.Typical project structure 2. Blueprints 3. Database 4. Forms & Validation 5. Management Commands 6. Assets-management 7. Replacement of django.contrib.admin 8. Debugging 9. Unit tests and Behavior tests
  • 12.
    Project structure 1. purepython module: settings.py - project - app.py - views.py - templates - static ... 2. Configuration: local_settings, settings: app.config.from_object(settings)
  • 13.
    Blueprints Kind of django-apps 1.Initialization: from flask import Blueprint app = Blueprint( 'profile', // namespace __name__, // logical python module or // package template_folder='templates', static_folder='static' ) ... @app.route('/sample/') def sample(): ...
  • 14.
    Register blueprint 1. Toregister use app.register_blueprint : from flask import Flask from proj.submodule.bp import app as submodule app = Flask(__name__) app.register_blueprint( submodule, url_prefix='/submodule' ) 2. Url namespace {{ url_for('profile.sample') }}
  • 15.
    Database Flask-SQLAlchemy minimongo Flask-Redis
  • 16.
    Flask-SQLAlchemy Example configuration fromdocs: from flask import Flask from flaskext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app)
  • 17.
    Flask-SQLAlchemy class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column( db.String(80), unique=True) email = db.Column( db.String(120), unique=True) def __init__(self, username, email): self.username = username self.email = email def __repr__(self): return '<User %r>' % self.username
  • 18.
    Flask-SQLAlchemy >>> from appimport db >>> db.create_all() >>> from app import User >>> admin = User('admin', 'admin@example.com') >>> guest = User('guest', 'guest@example.com') >>> db.session.add(admin) >>> db.session.add(guest) >>> db.session.commit() >>> User.query.all() [<User u'admin'>, <User u'guest'>]
  • 19.
    Minimongo 1. Noinitial configuration needed 2. Install & start mongo - that's enough Sample model: import minimongo as mm class Profile(mm.Model): class Meta: database = "sampleproject" collection = "profiles" indices = (mm.Index('username'))
  • 20.
    Minimongo >>> from appimport db, User, Profile >>> admin = User.query.filter_by( ... username='admin').first() >>> admin.username u'admin' >>> profile = Profile(username=admin.username, ... description=u'Flask devleoper') >>> profile {'username': u'admin', 'description': u'Flask devleoper'} >>> profile.save() {'username': u'admin', '_id': ObjectId('4f13e019486dd09335000001'), 'description': u'Flask devleoper'}
  • 21.
    Minimongo >>> Profile.collection Collection(Database(Connection('localhost', 27017), u'sampleproject'),u'profiles') >>> Profile.collection.find_one( ... {'username': admin.username}) {u'username': u'admin', u'_id': ObjectId('4f13df60486dd09335000000'), u'description': u'Flask devleoper'}
  • 22.
    Flask-Redis 1. Install flask-redis 2.Add to app.py: from flask.ext.redis import init_redis ... redis = init_redis(app) 2. Quite easy to use: >>> from app import redis >>> p = redis.pipeline() >>> p.set("username", "admin") <redis.client.Pipeline object at 0x10139b350> >>> p.execute() [True] >>> redis.get("username") 'admin'
  • 23.
  • 24.
    WTForms Form andView from flask.ext import wtf class UserForm(wtf.Form): username = wtf.TextField("Username", [wtf.Required()]) email = wtf.TextField( "Email", [wtf.Required(), wtf.Email()]) @app.route('/form', methods=['POST', 'GET']) def form(): form = UserForm() if form.validate_on_submit(): flash("Success") return redirect("/form") return render_template("form.html", form=form)
  • 25.
    WTForm Template {% withmessages = get_flashed_messages() %} {{ ", ".join(messages or []) }} {% endwith %} <hr /> <form method="post" action="/form">{{ form.csrf }} <i>{{ "; ".join(form.username.errors) }}</i> <br /> {{ form.username(size=20) }} <hr /> {{ "; ".join(form.email.errors) }}<br /> {{ form.email(size=20) }} <hr /> <input type="submit" value="Go"> </form>
  • 26.
    Management Commands Write externalscripts with current project context
  • 27.
    Flask-Script 1. Create manage.pyscript within your project directory and put (which is quite similar to Django's manage.py): from flaskext.script import Manager from app import app manager = Manager(app) @manager.command def hello(): print "hello" if __name__ == "__main__": manager.run()
  • 28.
    Flask-Script maxk$ python manage.py shell Runs a Python shell inside Flask application context. hello runserver Runs the Flask development server i.e. app.run() maxk$ python manage.py hello hello
  • 29.
    Flask-Script With Flask-Script youable to: • Write custom management commands • Use existing ones like in flask-assets • Getting user's input • Use command line options All of abilities above already automated with Flask-Script and it's really easy-to-use.
  • 30.
  • 31.
    JS/CSS minification andso on Flask-Assets based on Webassets. To integrate we need some work to do: 1. Install Flask-Assets 2. Initialize Flask-Assets environment 3. Add Assets Bundles 4. Configure compressors/minifiers etc. to optimize our assets 5. Generate bundles with management command
  • 32.
    Flask-Assets: initializing environment importFlask from flask.ext.assets import Environment as AssetsEnvironment app = Flask(__name__) assets = AssetsEnvironment(app) assets.debug = True app.config['ASSETS_DEBUG'] = True app.config['YUI_COMPRESSOR_PATH'] = 'contrib/ yuicompressor-2.4.6.jar'
  • 33.
    Flask-Assets: Adding files Iwill show work with JavaScript only but feel free to use same approach with CSS files. JavaScript files directory structure: - static - js - src - core * jquery.js * underscore.js - app * module1.js * module2.js
  • 34.
    Flask-Assets: adding bundles assets.py: fromflaskext.assets import Bundle def register_assets(assets): core = Bundle( 'js/src/core/jquery.js', 'js/src/core/underscore.js', filters='yui_js', output='js/bundle/core.js' ) assets.register('core', core)
  • 35.
    Flask-Assets: adding bundles ... app= Bundle( 'js/src/app/*.js', filters='yui_js', output='js/bundle/app.js' ) assets.register('app', app)
  • 37.
    Flask-Assets: how touse Somewhere in your template code: {% assets "core" %} <script src="{{ ASSET_URL }}"></script> {% endassets %} {% assets "app" %} <script src="{{ ASSET_URL }}"></script> {% endassets %}
  • 38.
    Flask-Assets: debug mode Flask-Assetsgenerate code below (debug mode): <script src="/static/js/src/core/jquery.js"></ script> <script src="/static/js/src/core/underscore.js"></ script> <script src="/static/js/src/app/module1.js"></ script> <script src="/static/js/src/app/module2.js"></ script>
  • 39.
    Flask-Assets: production mode Flask-Assetsgenerate code below (production mode): <script src="/static/js/bundles/core.js"></script> <script src="/static/js/bundles/app.js"></script> Static files was generated with Flask-Script command: maxk$ python manage.py assets rebuild
  • 40.
    More extensions: Flask-Mail Flask-Babel Flask-Cache Flask-csrf Flask-FlatPages Flask-lesscss ...
  • 41.
  • 42.
    Tests Unit, Behavior andJavaScript tests
  • 44.
    Testing: Unit &Behavior To test templates, views etc we need to have request context Before execution: self.app.test_request_context().push() After execution: self.app.test_request_context().pop()
  • 45.
    Behavior Testes withLettuce Example feature and scenario: Feature: Auth Scenario: Sign In as featured expert When I go to "auth.login" view Then I see that response code is 200 And There's form with following fields: | form__username | | form__password | Fill the field "form__username" with "featured"
  • 46.
    lettuce-web Lettuce-web is alibrary which very close to headless testing using twill. lettuce-web doesn't require browser. You can write your features using lettuce-web predefined steps. More here: https://github.com/joymax/lettuce-web
  • 47.
    Flask-Jasmine Flask-Jasmine is extensionto execute Jasmine JavaScript Tests More details https://github.com/joymax/flask-jasmine
  • 48.
  • 49.
    Issues What's going onin Flask world at the moment?
  • 50.
    Python 3 Status ofporting Flask to Python 3 is unknown. Werkzeug not ported yet. Hopefully, will be ported to Python 3.3 ( PEP 414 for details)
  • 51.
    Werkzeug Werkzeug is reallyhuge and have tons of tools. Flask based on Werkzeug. We all like Python for small, robust and clean libraries.
  • 52.
  • 53.
    That's all Questions? Source:  https://github.com/joymax/kyivpy-flask-in-details