Categories
Flask

Python Web Development with Flask — Form Validation and Template Inheritance

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Form Validation with WTForms

We can add form validation into our Flask app with the WTForms library.

To install the library, we run:

pip install wtforms

Then we can use it by writing:

from flask import Flask, request
from wtforms import Form, BooleanField, StringField, PasswordField, validators
app = Flask(__name__)

class RegistrationForm(Form):
    username = StringField('Username', [validators.Length(min=4, max=25)])
    email = StringField('Email Address', [validators.Length(min=6, max=35)])
    password = PasswordField('New Password', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='Passwords must match')
    ])
    confirm = PasswordField('Repeat Password')
    accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])

@app.route('/register', methods=['POST'])
def register():
    form = RegistrationForm(request.form)
    if request.method == 'POST':
        if form.validate():
            return 'thanks for registering'
        else:
            return 'registration failed'



We create the RegistrationForm class that extends the Form class from wtforms .

We add the fields in there with the built in constructors.

StringField creates a string field.

The first argument is the name.

The 2nd argument has the validation rules.

validators.length checks the length.

PasswordField creates a password field.

BooleanField creates a boolean field.

validators.DataRequired() lets us make a field required.

We can show fields and registration messages in our template by using a macro.

For example, we can write:

app.py

from flask import Flask, request, render_template
from wtforms import Form, BooleanField, StringField, PasswordField, validators
app = Flask(__name__)

class RegistrationForm(Form):
    username = StringField('Username', [validators.Length(min=4, max=25)])
    email = StringField('Email Address', [validators.Length(min=6, max=35)])
    password = PasswordField('New Password', [
        validators.DataRequired(),
        validators.EqualTo('confirm', message='Passwords must match')
    ])
    confirm = PasswordField('Repeat Password')
    accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])

@app.route('/register', methods=['GET','POST'])
def register():
    form = RegistrationForm(request.form)
    if request.method == 'POST' and form.validate():
        return 'thanks for registering'
    return render_template('register.html', form=form)

templates/_formhelpers.html

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

templates/register.html

{% from "_formhelpers.html" import render_field %}
<form method=post>
  <dl>
    {{ render_field(form.username) }}
    {{ render_field(form.email) }}
    {{ render_field(form.password) }}
    {{ render_field(form.confirm) }}
    {{ render_field(form.accept_tos) }}
  </dl>
  <p><input type=submit value=Register>
</form>

We create the render_field macro that we use with the register.html template.

The field function renders the field.

field.errors renders the errors.

In the register.html file, we call render_field to render the fields with the errors with the render_field macro.

Template Inheritance

We can inherit from a base template so we can have shared items in there.

For example, we can write:

app.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route('/')
def register():
    return render_template('index.html')

templates/layout.html

<!doctype html>
<html>
  <head>
    {% block head %}
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
    <title>{% block title %}{% endblock %} - My Webpage</title>
    {% endblock %}
  </head>
  <body>
    <div id="content">{% block content %}{% endblock %}</div>
    <div id="footer">
      {% block footer %}
      &copy; Copyright 2010 by <a href="http://domain.invalid/">you</a>.
      {% endblock %}
    </div>
  </body>
</html>

templates/index.html

{% extends "layout.html" %}
{% block title %}Index{% endblock %}
{% block head %}
  {{ super() }}
  <style type="text/css">
    .important { color: #336699; }
  </style>
{% endblock %}
{% block content %}
  <h1>Index</h1>
  <p class="important">
    Welcome on my awesome homepage.
{% endblock %}

static/style.css

body {
    font-size: 20px;
}

In layout.html , we add the blocks with the block keyword.

Then we override them with our own content with the index.html template.

Conclusion

We can add form validation and base templates with Flask.

Categories
Flask

Python Web Development with Flask — SQLAlchemy ORM

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Using Flask with SQLAlchemy

We can use Flask with the SQLAlchemy ORM.

First, we install the sqlalchemy package by running:

pip install sqlalchemy

Next, we create the database file with the SQLite browser app.

We create a people table with the id integer primary key column and the name text column.

Then we have the file as database.db in the root of the Flask project folder.

Then, we can write to use it:

from flask import Flask, g
from sqlalchemy import create_engine, MetaData, Table, Column, Integer, String
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.orm import mapper

engine = create_engine('sqlite:///database.db', convert_unicode=True)
metadata = MetaData(bind=engine)
db_session = scoped_session(sessionmaker(autocommit=False,
                                         autoflush=False,
                                         bind=engine))

metadata.create_all(bind=engine)
app = Flask(__name__)

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

class Person(object):
    query = db_session.query_property()

    def __init__(self, name=None, id=None):
        self.name = name
        self.id = id

    def __repr__(self):
        return '<Person %r>' % (self.name)

people = Table('people', metadata,
              Column('id', Integer, primary_key=True),
              Column('name', String(50), unique=True),
              )
mapper(Person, people)

@app.route('/')
def index():
    person = people.select(people.c.id == 1).execute().first()
    return person.name

We connect to the database with the create_engine call.

Then we create the Metadata object so tjhat we can create models that uses the database connection.

Then we call scoped_session to create the database session.

autocommit set to false disables auto commit.

autoflush sets to false disabled auto flush.

bind set to engine binds the database session to our connection.

Then we call metadata.create_all to bind the engine to our app so we can create Table objects that uses the connection for queries.

Then we have the shutdown_sesion function that calls db_session.remove to disconnect the database when the app stops running.

Next, we create the Person class to add the query into our app.

This lets us use the class to query the database.

The __init__ method sets the instance properties with the names from the database columns.

__repr__ returns the string representation of the entry.

Then we use the Table construictor to create the people table object with the id and name columns.

They should match what we have in the database.

Then we call mapper to map the Person class to the people table.

Finally, in the index route function, we make a query in the table and then return the first result with first .

Then we return the value of the name column of the result.

To insert data, we change index to:

@app.route('/')
def index():
    con = engine.connect()
    con.execute(people.insert(), name='bob')
    person = people.select(people.c.id == 1).execute().first()
    return person.name

Everything above this function is the same as what we have before.

We connect to the database with engine.connect() .

Then we call con.execute to run the connect, people.insert() indicates we’re inserting an entry.

name indicates that we’re inserting to the name column.

Conclusion

We can use the SQLAlchemy ORM with Flask easily.

Categories
Flask

Python Web Development with Flask — URL Processors and SQLite

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

URL Processors

We can add a URL processor to let us share resources with similar URLs.

With it, we don’t have to specify different routes that map to similar URLs.

For example, we can write:

from flask import Flask, g, request

app = Flask(__name__)

@app.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@app.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

@app.route('/<lang_code>/')
def index():
    return 'index %s' % g.lang_code

@app.route('/<lang_code>/about')
def about():
    return 'about %s' % g.lang_code

to add a URL preprocessor, which is run before the route functions are run.

The add_language_code function is run to set the lang_code from the g.lang_code property if it exists.

The app.url_map.is_endpoint_expecting method is used to check if the lang_code URL parameter is expected.

The URL preprocessor function is the pull_lang_code function.

We use the @app.url_value_preprocessor decorator to register the URL preprocessor function.

values has the URL parameters.

Then we call values.pop to get the value of the 'lang_code' URL parameter and set that as the value of g.lang_code .

Then in our route functions, we can omit the lang_code parameter.

We get the value for lang_code from the g.lang_code property instead.

So when we go to http://127.0.0.1:5000/en/about, we see ‘about en’.

And when we go to http://127.0.0.1:5000/en/, we see ‘index en’.

Internationalized Blueprint URLs

We can add URL preprocessors for blueprints.

For example, we can write:

from flask import Flask, g, request, Blueprint

app = Flask(__name__)
bp = Blueprint('frontend', __name__, url_prefix='/<lang_code>')

@bp.url_defaults
def add_language_code(endpoint, values):
    if 'lang_code' in values or not g.lang_code:
        return
    if app.url_map.is_endpoint_expecting(endpoint, 'lang_code'):
        values['lang_code'] = g.lang_code

@bp.url_value_preprocessor
def pull_lang_code(endpoint, values):
    g.lang_code = values.pop('lang_code', None)

@bp.route('/')
def index():
    return 'index %s' % g.lang_code

@bp.route('/about')
def about():
    return 'about %s' % g.lang_code

app.register_blueprint(bp)

We create the bp blueprint with the Blueprint constructor.

It has the url_prefix parameter to make it accept the lang_code URL parameter as the prefix.

Then we add the same URL preprocessor function as we do before to get the lang_code parameter and set it as the value of the g.lang_code property.

The difference is that we use the @bp.url_value_preprocessor decorator to register the URL preprocessor.

The @bp.url_defaults decorator is used to setting the default value of the lang_code URL parameter.

Then the bp blueprint routes can be used the same way as we do before.

After defining the routes, we call app.register_blueprint to register the bp blueprint.

SQLite 3 with Flask

We can use SQLite 3 with Flask.

To do this, we can write:

from flask import Flask, g
import sqlite3

app = Flask(__name__)
DATABASE = './database.db'

def get_db():
    db = getattr(g, '_database', None)
    if db is None:
        db = g._database = sqlite3.connect(DATABASE)
    return db

@app.teardown_appcontext
def close_connection(exception):
    db = getattr(g, '_database', None)
    if db is not None:
        db.close()

def query_db(query, args=(), one=False):
    cur = get_db().execute(query, args)
    rv = cur.fetchall()
    cur.close()
    return (rv[0] if rv else None) if one else rv

@app.route('/')
def index():
    names = []
    for person in query_db('select * from people'):
        names.append(person[0])
    return ','.join(names)

We create the get_db function to connect to the database.

close_connection closes the connection.

It’s run when we stop the app as indicated by the @app.teardown_context decorator.

The query_db function queries the data with the get_db function to make the connection.

Then we fetch all the items returned by the query .

It returns the result, and we use that in our index route function.

We created a people table with the name text column.

So person[0] returns the value of the name column.

Conclusion

We can add URL processors to make managing similar URLs easier.

Also, we can use SQLite with our app.

Categories
Flask

Python Web Development with Flask — Commands and Blueprints, Factories, and Exceptions

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Registering Commands with Blueprints

We can register commands with Blueprints.

For example, we can write:

from flask import Flask
import click
from flask import Blueprint
app = Flask(__name__)
bp = Blueprint('students', __name__)

@bp.cli.command('create')
@click.argument('name')
def create(name):
    print('create %s' % name)

app.register_blueprint(bp)

@app.route('/')
def hello_world():
    return 'hello world'

We create our blueprint with the Blueprint class.

Then we call @bp.cli.command decorator to create the 'create' command in the blueprint.

We specify the command line argument with the @click.argument decorator.

Then we call app.register_blueprint to register the blueprint.

Then when we run:

flask students create alice

We see ‘created alice’ displayed.

Application Context

We can use the @with_appcontext decorator to run the command function with the app context pushed.

This way, we have access to the app and its config in the command function.

For example, we can write:

from flask import Flask
import click
from flask.cli import with_appcontext
app = Flask(__name__)

@click.command('do_work')
@with_appcontext
def do_work():
    print(app)

app.cli.add_command(do_work)

@app.route('/')
def hello_world():
    return 'hello world'

to add the do_work task into our app.

When we run:

flask do_work

we see the app:

<Flask 'app'>

logged.

Application Factories

We can create a factory function for our app so that we can create multiple instances of our app.

This makes testing easier.

For example, we can write:

from flask import Flask

def create_app(config_filename):
    app = Flask(__name__)
    app.config.from_object(config_filename)
    print(app.config)

    @app.route('/')
        def hello_world():
            return 'hello world'
    return app

create_app('config')

to create a create_app function that takes the config_filename parameter.

Then we can read the config parameter we want according to the value of config_filename .

API Exceptions

We can create our own exception classes and use them in our Flask app.

For example, we can write:

from flask import Flask, jsonify

class InvalidUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv

app = Flask(__name__)

@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response

@app.route('/')
def hello_world():
    raise InvalidUsage('This view is gone', status_code=410)

We create the InvalidUsage class which extends the Exception class.

The __init__ method initializes the mesaage and payload values.

to_dict is a method that puts the instance variables into a dictionary and returns it.

Then we register the error handler for this exception with the handle_invalid_usage method.

The @app.errorhandler decorator is used to handle the errors.

In the function, we call error.to_dict() to get the dictionary version of the error and returns it as the JSON response.

Then in the hello_world route function, we raise the InvalidUsage exception.

And when we go to http://127.0.0.1:5000/, we see:

{
  "message": "This view is gone"
}

in the response.

Conclusion

We can register commands with blueprints, create app factory functions, and add our own API exceptions with Flask.

Categories
Flask

Python Web Development with Flask — Blueprints and Commands

Flask is a simple web framework written in Python.

In this article, we’ll look at how to develop simple Python web apps with Flask.

Blueprints

We can use Blueprints to modularize our apps with Flask.

For example, we can write:

app.py

from flask import Flask, request
from simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page)

simple_page.py

from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound

simple_page = Blueprint('simple_page', __name__,
                        template_folder='templates')

@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
    try:
        return render_template('pages/%s.html' % page)
    except TemplateNotFound:
        abort(404)

templates/pages/users.html

<p>users</p>

In the simple_pages.py file, we create the blueprint.

We create it with the Blueprint class.

The first argument is the name.

The 3rd argument is the template folder location.

Then to create a route, we call route on the simple_page blueprint.

The defaults parametrer has a dict that has the default value for the page URL parameter.

Then in the function, we call render_template to render the template with the given file name.

In app.py , we call app.register_blueprint to register the blueprint.

When we go to http://127.0.0.1:5000/users, we see ‘users’ displayed.

We can add a URL prefix for the blueprint.

For example, we can write:

app.py

from flask import Flask, request
from simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page, url_prefix='/pages')

simple_page.py

from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound

simple_page = Blueprint('simple_page', __name__,
                        template_folder='templates')

@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
    print(page)
    try:
        return render_template('pages/%s.html' % page)
    except TemplateNotFound:
        abort(404)

templates/pages/users.html

<p>users</p>

We add the url_prefix parameter into the app.register_blueprint to add the URL prefix.

When we go to http://127.0.0.1:5000/pages/users, we see ‘users’ displayed.

Static Files

We can add a static files folder with Blueprints.

To do that, we pass in the static_folder parameter.

To do that, we write:

app.py

from flask import Flask, request
from simple_page import simple_page

app = Flask(__name__)
app.register_blueprint(simple_page, url_prefix='/pages')

simple_page.py

from flask import Blueprint, render_template, abort
from jinja2 import TemplateNotFound

simple_page = Blueprint('simple_page', __name__,
                        template_folder='templates',
                        static_folder='static')

@simple_page.route('/', defaults={'page': 'index'})
@simple_page.route('/<page>')
def show(page):
    print(page)
    try:
        return render_template('pages/%s.html' % page)
    except TemplateNotFound:
        abort(404)

static/styles.css

body {
    font-weight: bold;
}

templates/pages/users.html

<link rel="stylesheet" href="{{ url_for('simple_page.static', filename='styles.css')
 }}">
<p>users</p>

In simple_page.py , we add the static_folder parameter to set the static folder location.

Then we put the styles.css in the static folder and set the styles we want.

In users.html , we have:

url_for('simple_page.static', filename='styles.css')

to get the path to the styles.css file.

Command Line Interface

We can add commands into our Flask app.

For example, we can write:

from flask import Flask
import click

app = Flask(__name__)

@app.cli.command("create-user")
@click.argument("name")
def create_user(name):
    print('create %s' % name)

@app.route('/')
def hello_world():
    return 'hello world'

We add the create-user command with the @app.cli.command decorator.

The name parameter is obtained from the name command-line argument.

The command-line argument is specified by the @click.argument decorator.

So when we run:

flask create-user admin

in the command line, we see ‘create admin’ displayed.

Also, we can put commands in groups.

For example, we can write:

from flask import Flask
import click
from flask.cli import AppGroup

app = Flask(__name__)
user_cli = AppGroup('user')

@user_cli.command('create')
@click.argument('name')
def create_user(name):
    print('create %s' % name)

app.cli.add_command(user_cli)

@app.route('/')
def hello_world():
    return 'hello world'

to add the 'user' command group.

Then we specify our commands in the group with the @user_cli.command decorator.

And we register the command with the app.cli.add_command method.

Now when we run:

flask user create demo

we see ‘create demo’ displayed.

Conclusion

We can organize our Flask apps with blueprints and add commands to our Flask app.