Read order

  1. 1 - Flask configurations
    1. venv
    2. flask config
    3. modularization
  1. 4 - Working with views
    1. routes
    2. templates
  1. 3 - Data modeling in Flask
    1. DB connection
    2. MVC example
    3. ORM relational example

1 Flask configurations

Introduction

Micro β‡’ because the core of framework it’s small but extensible.
First example
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello to the World of Flask!' if __name__ == '__main__': app.run()
An instance of the imported Flask class is a Web Server Gateway Interface (WSGI) application.
πŸ’‘
Never save your application file as flask.py; if you do so, it will conflict with Flask itself while importing.

Environment setup with virtualenv

Para crear y activar un entorno virtual:
$ pip install virtualenv $ virtualenv my_flask_app_name $ cd my_flask_app_name/Source $ activate $ pip install flask
This will activate our environment and install Flask inside it. Now, we can do anything with our application within this environment, without affecting any other Python environment.
πŸ’‘
$ pip install -U flask In the preceding command, -U refers to the installation with upgrades. This will overwrite the existing installation (if any) with the latest released versions.
Desactivar un entorno virtual
$ deactivate

Handling basic configurations

In Flask, a configuration is done on an attribute named config of the Flask object. The config attribute is a subclass of the dictionary data type, and we can modify it just like any dictionary.
app = Flask(__name__) app.config['DEBUG'] = True
The debug Boolean can also be set at the Flask object level rather than at the config level:
Alternatively, we can use this line of code:
app.debug = True
app.run(debug=True)
Enabling the debug mode will make the server reload itself in the case of any code changes, and it also provides the very helpful Werkzeug debugger when something goes wrong.
πŸ’‘
From a Python configuration file (*.cfg), the configuration can be fetched using: app.config.from_pyfile('myconfig.cfg')
From an object, the configuration can be fetched using:
app.config.from_object('myapplication.default_settings')
Alternatively, we can also use:
app.config.from_object(name) #To load from same file
ff From the environment variable, the configuration can be fetched using:
app.config.from_envvar('PATH_TO_CONFIG_FILE')
πŸ’‘
The best practice to use configurations is to have a bunch of default settings in app.py or via any object in our application itself and then override the same by loading it from the configuration file.

Class-based settings

Use the inheritance pattern to be able different environments of configurations.
class BaseConfig(object): 'Base config class' SECRET_KEY = 'A random secret key' DEBUG = True TESTING = False NEW_CONFIG_VARIABLE = 'my value' class ProductionConfig(BaseConfig): 'Production specific config' DEBUG = False SECRET_KEY = open('/path/to/secret/file').read() class StagingConfig(BaseConfig): 'Staging specific config' DEBUG = True class DevelopmentConfig(BaseConfig): 'Development environment specific config' DEBUG = True TESTING = True SECRET_KEY = 'Another random secret key'
πŸ’‘
The secret key is stored in a separate file because, for security concerns, it should not be a part of your version-control system. This should be kept in the local filesystem on the machine itself, whether it is your personal machine or a server.
Let's say that we save the preceding class-based configuration in a file named configuration.py:
app.config.from_object('configuration.DevelopmentConfig')
Example code

Organization of static files

Flask recommends a specific way to organize static files in our application:
my_app/ - app.py - config.py - __init__.py - static/ - css/ - js/ - images/ - logo.png
You can use in some template like this:
<img src='/static/images/logo.png'>
πŸ’‘
Alternative, you can specify the static route like this: app = Flask(name, static_folder='/path/to/static/folder') <img src='{{ url_for('static', filename="logo.png")}}'>

Being deployment specific with instance folders

We know that configuration files can be separate for different deployment environments such as development and production, but there are many more files such as database files, session files, cache files, and other runtime files. So, we can say that an instance folder is like a holder bin for these kinds of files.
my_app/ - app.py - instance/ - config.cfg
app = Flask(__name__, instance_path='/absolute/path/to/instance/folder')
To load the configuration file from the instance folder, we will use the instance_relative_ config parameter on the application object:
app = Flask( __name__, instance_path='path/to/instance/folder', instance_relative_config=True ) app.config.from_pyfile('config.cfg', silent=True)
In the preceding code, first, the instance folder is loaded from the given path, and then, the configuration file is loaded from the file named config.cfg in the given instance folder. Here, silent=True is optional and used to suppress the error in case config.cfg is not found in the instance folder.

Composition of view models

// Do nothing

Creating a modular web app with blueprints

A blueprint is actually a set of operations that can be registered on an application and represents how to construct or build an application.
Create a blueprint
from flask import Blueprint hello = Blueprint('hello', __name__) @hello.route('/') @hello.route('/hello') def hello_world(): return MESSAGES['default']
Register a blueprint
from flask import Flask from my_app.hello.views import hello app = Flask(__name__) app.register_blueprint(hello)

Making a Flask app installable using setuptools

So, we have a Flask application now, but how do we install it just like any Python package? It is possible that any other application depends on our application or our application is in fact an extension for Flask and would need to be installed in a Python environment so that it can be used by other applications.
// Do nothing

2 Templating with Jinja2

3 Data modeling in Flask

Introduction

The models are virtually non-existent and everything happens in the view functions, where we write queries to interact with the DB.
In this chapter, we will talk about creating an ORM layer for our Flask applications with SQLAlchemy for relational database systems.
πŸ’‘
ORM refers to Object Relational Mapping/Modeling and implies how our application's data models store and deal with data at a conceptual level. A powerful ORM makes designing and querying business logic easy and streamlined.

Creating a SQLAlchemy DB instance

SQLAlchemy is a Python SQL toolkit and provides an ORM that gives the flexibility and power of SQL with the feel of Python's object-oriented nature.

Getting ready

  • Install
pip install flask-sqlalchemy
  • Config
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ('DATABASE_URI')
This SQLALCHEMY_DATABASE_URI is a combination of the database protocol, any authentication needed, and also the name of the database.
In the case of PostgreSQL, it would look like the following:
postgresql://yourusername:yourpassword@localhost/yournewdb
http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html#database-urls
πŸ’‘
For all database systems other than SQLite, separate libraries are needed. For example, for using PostgreSQL, you would need psycopg2

How to do it

from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app)

Creating a basic product model

  • App
from flask import Flask from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' db = SQLAlchemy(app) from my_app.catalog.views import catalog app.register_blueprint(catalog) db.create_all()
The last statement in the file is db.create_all(), which tells the application to create all the tables in the database specified. So, as soon as the application runs, all the tables will be created if they are not already there.
  • Model
from my_app import db class Product(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) price = db.Column(db.Float) def __init__(self, name, price): self.name = name self.price = price def __repr__(self): return '<Product %d>' % self.id
In this file, we have created a model named Product that has three fields, namely id, name, and price. The id field is a self-generated field in the database that will store the ID of the record and is the primary key. name is a field of type string and price is of type float.
  • Views
from flask import request, jsonify, Blueprint from my_app import app, db from my_app.catalog.models import Product catalog = Blueprint('catalog', __name__) @catalog.route('/') @catalog.route('/home') def home(): return "Welcome to the Catalog Home." @catalog.route('/product/<id>') def product(id): product = Product.query.get_or_404(id) return f'Product - {product.name}, {product.price}' @catalog.route('/products') def products(): products = Product.query.all() res = {} for product in products: res[product.id] = { 'name': product.name, 'price': str(product.price) } return jsonify(res) @catalog.route('/product-create', methods=['POST',]) def create_product(): name = request.form.get('name') price = request.form.get('price') product = Product(name, price) db.session.add(product) db.session.commit() return 'Product created.'

Creating a relational category model

  • Models
from my_app import db class Product(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) price = db.Column(db.Float) category_id = db.Column(db.Integer,db.ForeignKey('category.id')) category = db.relationship( 'Category', backref=db.backref('products', lazy='dynamic') ) def __init__(self, name, price, category): self.name = name self.price = price self.category = category def __repr__(self): return '<Product %d>' % self.id class Category(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) def __init__(self, name): self.name = name def __repr__(self): return '<Category %d>' % self.id
  • Views
from my_app.catalog.models import Product, Category @catalog.route('/products') def products(): products = Product.query.all() res = {} for product in products: res[product.id] = { 'name': product.name, 'price': product.price, 'category': product.category.name } return jsonify(res) @catalog.route('/product-create', methods=['POST',]) def create_product(): name = request.form.get('name') price = request.form.get('price') categ_name = request.form.get('category') category = Category.query.filter_by(name=categ_name).first() if not category: category = Category(categ_name) product = Product(name, price, category) db.session.add(product) db.session.commit() return 'Product created.' @catalog.route('/categories') def categories(): categories = Category.query.all() res = {} for category in categories: res[category.id] = { 'name': category.name } for product in category.products: res[category.id]['products'] = { 'id': product.id, 'name': product.name, 'price': product.price } return jsonify(res)

Database migration using Alembic and Flask-Migrate

// Do nothing

Model data indexing with Redis

// Do nothing

Opting the NoSQL way with MongoDB

// Do nothing

4 Working with views

Writing function-based views and URL routes

We can just write a method and decorate it with the endpoint.
@app.route('/a-get-request') def get_request(): bar = request.args.get('foo', 'bar') return 'A simple Flask request where foo is %s' % bar @app.route('/a-post-request', methods=['POST']) def post_request(): bar = request.form.get('foo', 'bar') return 'A simple Flask request where foo is %s' % bar
Other way to do this:
def get_request(): bar = request.args.get('foo', 'bar') return 'A simple Flask request where foo is %s' % bar app = Flask(__name__) app.add_url_rule('/a-get-request', view_func=get_request)

Class-based views

from flask.views import View class GetRequest(View): methods = ['GET'] def dispatch_request(self): bar = request.args.get('foo', 'bar') return 'A simple Flask request where foo is %s' % bar app.add_url_rule('/a-get-request', view_func=GetRequest.as_view('get_request'))

URL routing and product-based pagination

Params

@app.route('/test/<string(minlength=2,maxlength=3):code>') def get_name(code): return code @app.route('/test/<int:age>') def get_age(age): return str(age)

Pagination

@catalog.route('/products') @catalog.route('/products/<int:page>') def products(page=1): products = Product.query.paginate(page, 10).items res = {} for product in products: res[product.id] = { 'name': product.name, 'price': product.price, 'category': product.category.name } return jsonify(res)

Rendering to tempates

from flask import render_template @catalog.route('/') @catalog.route('/home') def home(): return render_template('home.html') @catalog.route('/product/<id>') def product(id): product = Product.query.get_or_404(id) return render_template('product.html', product=product)
The flask_catalog_template/my_app/templates/home.html file looks as follows:
{% extends 'base.html' %} {% block container %} <h1>Welcome to the Catalog Home</h1> <a href="{{ url_for('catalog.products') }}">Click here to see the catalog</a> {% endblock %}
The flask_catalog_template/my_app/templates/product.html file looks as follows:
{% extends 'home.html' %} {% block container %} <div class="top-pad"> <h1>{{ product.name }}<small> {{ product.category.name }}</small></h1> <h4>{{ product.company }}</h4> <h3>{{ product.price }}</h3> </div> {% endblock %}

Dealing with XHR requests

// Do nothing

Decorator to handle requests beautifully

// Do nothing

Creating custom 404 and 500 handlers

@handler.errorhandler(TaskNotFoundError) def handler_not_found_error(error: TaskNotFoundError): return error.message

Flashing messages for better user feedback

// Do nothing

SQL-based searching

// Do nothing
badge