Categories
Flask

Python Web Development with Flask — Template Functions and Filters

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.

Templates

Flask comes with the Jinja template engine.

We can use it to render HTML.

It can access the config , request , session , g ,url_for , and get_flashed_messages contexts.

config is the current configuration object.

request is the current request object.

session is the current session object.

g us the request bound object for global variables.

url_for is the url_for function.

And get_flashed_messages is the get_flashes_messages function.

Standard Filters

We can use filters that are provided by Flask and Jinja.

For example, we can write:

app.py

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

@app.route('/')
def hello_world():
    user = {
        'first_name': 'james',
        'last_name': 'smith'
    }
    return render_template('index.html', user=user)

templates/index.html

<script type=text/javascript>
    const user = {{ user|tojson }};
</script>

to add the user dictionary.

Then we pass the user object into the template and use the tojson filter with it to convert the dictionary to JSON.

So we get:

<script type="text/javascript">
    const user = {"first_name": "james", "last_name": "smith"};
</script>

rendered in the template.

Autoescaping

We can disable autoescaping with the autoescape false block.

For example, we can write:

app.py

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

@app.route('/')
def hello_world():
    return render_template(
        'index.html',
        will_not_be_escaped='<b>will_not_be_escaped</b>'
    )

templates/index.html

{% autoescape false %}
<p>{{ will_not_be_escaped }}</p>
{% endautoescape %}

The will_not_be_escaped isn’t escaped, so the raw HTML string is rendered.

So we’ll see the <b> tag rendered as bold text.

Registering Filters

We can register our own filters.

For example, we can write:

app.py

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

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

@app.route('/')
def hello_world():
    return render_template(
        'index.html',
        arr=[1, 2, 3]
    )

templates/index.html

{% for a in arr | reverse %}
    <p>{{a}}</p>
{% endfor %}

We register the reverse filter with the app.template_filter decorator.

In the reverse_filter function, we return the reversed array s .

Then in the template, we use the reverse filter and render it.

We can also write:

app.py

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

def reverse_filter(s):
    return s[::-1]

app.jinja_env.filters['reverse'] = reverse_filter

@app.route('/')
def hello_world():
    return render_template(
        'index.html',
        arr=[1, 2, 3]
    )

to do the same thing.

We put the filter in the app.jinja_env.filters dictionary.

Context Processors

We can add functions that we can run in templates.

To do that, we use the @app.context_processor decorator.

For example, we can write:

app.py

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

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

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

templates/index.html

{{ format_price(1.22) }}

We add th utility_processor function and applied the @app.context_processor to it.

Then inside it, we created the format_price function that returns a formatted currency string.

And then we return a dictionary with the function as the value of the format_price key.

Now we can call it in index.html to render a currency string.

Conclusion

We can call functions and use filters in templates with Flask.

Categories
Flask

Python Web Development with Flask — Logging, App Commands, and Blueprints

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.

Logging

Flask comes with a logger.

We can use it with the app.logger object.

For example, we can write:

from flask import Flask
from markupsafe import escape

app = Flask(__name__)

@app.route('/')
def index():
    app.logger.debug('A value for debugging')
    app.logger.warning('A warning occurred (%d apples)', 42)
    app.logger.error('An error occurred')
    return 'hello'

to call methods to do various levels of logging.

Add App Commands

We can add app commands with Flask.

This way, we can automate tasks that are otherwise manual.

For example, we can create a task to initialize a database by writing:

app.py

from flask import Flask, current_app, g
import os
import sqlite3
import click
from flask.cli import with_appcontext

def get_db():
    if 'db' not in g:
        g.db = sqlite3.connect(
            'db.sqlite',
            detect_types=sqlite3.PARSE_DECLTYPES
        )
        g.db.row_factory = sqlite3.Row
    return g.db

def close_db(e=None):
    db = g.pop('db', None)
    if db is not None:
        db.close()

def init_db():
    db = get_db()
    with current_app.open_resource('schema.sql') as f:
        db.executescript(f.read().decode('utf8'))

@click.command('init-db')
@with_appcontext
def init_db_command():
    init_db()
    click.echo('Initialized the database.')

app = Flask(__name__)
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)

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

schema.sql

DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;

CREATE TABLE user (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  password TEXT NOT NULL
);

CREATE TABLE post (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  author_id INTEGER NOT NULL,
  created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  title TEXT NOT NULL,
  body TEXT NOT NULL,
  FOREIGN KEY (author_id) REFERENCES user (id)
);

The following code:

@click.command('init-db')
@with_appcontext
def init_db_command():
    init_db()
    click.echo('Initialized the database.')

creates our command.

We pass in the command name into the @click.command decorator.

init-db is the name of the command we registered.

The with_appcontext decorator is also required to use the app context.

In the init_db function, we call get_db to get the database connection.

Then we call current_app.open_resource to get the SQL script with the and run it with db.executescript .

We call:

app.teardown_appcontext(close_db)

to close the database connection.

Now we run:

flask init-db

to run the init-db command to run our schema.sql script to create the tables.

Blueprints

To separate our apps into smaller modules, we can use blueprints.

For example, we can write:

app.py

from flask import Flask
from auth import bp
app = Flask(__name__)
app.register_blueprint(bp)

auth.py

from flask import Blueprint

bp = Blueprint('auth', __name__, url_prefix='/auth')
@bp.route('/register', methods=('GET', 'POST'))
def register():
    return 'register'

to create the auth blueprint.

We use the Blueprint class to create the blueprint.

The first argument is the name.

__name__ is the location that the blueprint is defined in.

The 3rd argument is the URL prefix.

To register a route in the blueprint, we call the @bp.route decorator like we do with the app.route decorator.

Then to register the blueprint, we write:

app.register_blueprint(bp)

to register the blueprint.

Conclusion

We can add logging, app commands, and blueprints with Flask.

Categories
Flask

Python Web Development with Flask — Errors, Sessions, and JSON

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.

Redirects and Errors

We can redirect to another endpoint in our Flask app.

To do that, we write:

from flask import Flask, abort, redirect, url_for
app = Flask(__name__)

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)

When we go to / , then we’re redirected to the /login route.

Then we get the 401 response because we called abort with the response.

We can create a 404 page by writing:

app.py

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

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

templates/page_not_found.html

<p>not found</p>

Now when we go to any URL, we render the page_not_found.html template with a 404 response status code.

Response Headers

We can return headers with our response by using the make_response function to create the response.

For example, we can write:

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

@app.errorhandler(404)
def page_not_found(error):
    resp = make_response(render_template('page_not_found.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

We have our 404 route.

In it, we create the response with the make_response function.

Then we pass in the template into function as the first argument.

The 2nd argument is the status code.

resp.headers is a dictionary with the headers.

Finally, we return the response object.

APIs with JSON

We can return JSON s our response.

To do that, all we have to do is return the dictionary for our JSON.

For example, we can write:

from flask import Flask
app = Flask(__name__)

@app.route("/me")
def me_api():
    return {
        "first_name": 'james',
        "last_name": 'smith'
    }

to return a dictionary in our route function.

It’ll be rendered as JSON automatically.

We can also use the jsonify function if we have anything other than a dictionary that we want to render into JSON:

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

@app.route("/me")
def me_api():
    users = [
        {
            'first_name': 'jane',
            'last_name': 'smith',
        },
        {
            'first_name': 'mary',
            'last_name': 'wong',
        },
    ]
    return jsonify(users)

Sessions

Flask can handle sessions automatically.

We can use the session object from the Flask module to store sessions.

For example, we can write:

from flask import Flask, session, request, redirect, url_for
from markupsafe import escape

app = Flask(__name__)
app.secret_key = b'secret'

@app.route('/')
def index():
    if 'username' in session:
        return 'Logged in as %s' % escape(session['username'])
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

We set the secret_key property to set the secret key.

In the index route function, we get the username value from the session object.

It’s a dictionary so we get the value by the key.

The login route function takes the username value from the form data if we’re making a POST request.

Then we redirect to index once that’s done.

If it’s a GET request, then we render the login form.

In the logout route function, we remove the value with the keyusername by setting it to None .

And then we redirect back to index .

Conclusion

We can do redirects, show error pages, store sessions, and return JSON easily with Flask.

Categories
Flask

Python Web Development with Flask — Request and Response

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.

The Request Object

We can get data from the request object.

To get form data, we can write:

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

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        if 'username' in request.form and 'password' in request.form:
            return '%s:%s' % (
                request.form['username'],
                request.form['password']
            )
        else:
            return 'Invalid username/password'

We check if 'username' and 'password' keys are in request.form .

request.form has the form data key-value pairs.

If they’re both present when we make the POST request to http://127.0.0.1:5000/login, then we return the username and password combined as the response.

Otherwise, we return ‘Invalid username/password’ .

Alternatively, we can write:

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

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        username = request.args.get('username', '')
        password = request.args.get('password', '')
        if username != '' and password != '':
            return '%s:%s' % (
                username,
                password
            )
        else:
            return 'Invalid username/password'

We call request.args.get to get the value with the given form data key.

The 2nd argument is the default value.

So we can check username and password against an empty string instead to see if they have a value or not.

File Uploads

We can accept file uploads with Flask.

For example, we can write:

from flask import Flask, request
from werkzeug.utils import secure_filename
app = Flask(__name__)

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('./uploads/%s' % (secure_filename(f.filename)))
        return 'file uploaded'

to add the upload route.

We check the upload_file function for the route.

Then we check if the method of the request is 'POST' .

If it is, then we get the file from request.files .

Then we save the file with f.save and the path to save to.

secure_filename creates an escaped file name.

f.filename has the file name of the file that’s sent with the request.

Cookies

We can get the cookies from the request with the request.cookies.get method.

For example, we can write:

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

@app.route('/')
def index():
    username = request.cookies.get('username')
    return username

Then when we add the Cookie request header with the value username=foo when we make a GET request to http://127.0.0.1:5000/, then we get the cookie with the key username with request.cookies.get .

It should return 'foo' for username , so that’s what we see in the response body.

Also, we can send cookies with the response.

To do that, we write:

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

@app.route('/')
def index():
    resp = make_response(render_template('index.html'))
    resp.set_cookie('username', 'the username')
    return resp

We call resp.set_cookie with the key and value of the cookie.

Then we return the response.

Conclusion

We can get request data and send cookie responses with Flask.

Categories
Flask

Python Web Development with Flask — Routes and Templates

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.

Unique URLs / Redirection Behavior

Adding a trailing slash to the URL will get us to access to the URL with our without a trailing slash.

For example, if we write:

from flask import Flask
app = Flask(__name__)

@app.route('/foo/')
def projects():
    return 'The foo page'

@app.route('/bar')
def about():
    return 'The bar page'

We only see ‘The bar page’ when we go to http://localhost:5000/bar.

On the other hand, if we go to http://localhost:5000/foo or http://localhost:5000/foo/, we see ‘The foo page’.

URL Building

We can use the url_for function to show the full URL of each route.

For example, we can write:

from flask import Flask, url_for
from markupsafe import escape

app = Flask(__name__)

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

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return '{}'s profile'.format(escape(username))

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='Jane Smith'))

Then in the with block, we print the full paths created from the routes.

We see:

/
/login
/login?next=%2F
/user/Jane%20Smith

url_for('index') returns ‘/‘.

url_for(‘login’) returns '/login' .

url_for(‘login’, next=’/’) returns ‘/login?next=%2F’ .

And url_for(‘profile’, username=’Jane Smith’) returns /user/Jane%20Smith .

We just pass in the function name into url_for as a string, and we get back the URL constructed from it.

HTTP Methods

A route function can take requests made with different HTTP methods.

We can restrict this with the methods parameter we pass into @app.route .

For example, we can write:

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return 'logged in'
    else:
        return 'login form'

We set the methods parameter to the [‘GET’, ‘POST’] to restrict the function to only accept GET and POST requests.

Then we can check the request method with the request.method property.

So if we make a POST request to http://127.0.0.1:5000/login, we get ‘logged in‘ returned.

And if we make a GET request to the same URL, we get ‘login form‘ returned.

Static Files

We can serve static files with Flask.

To do that, we write:

app.py

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

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

with app.test_request_context():
    print(url_for('static', filename='style.css'))

static/style.css

body {
    font-weight: bold;
}

We print the path to the style.css static file in the static folder with the url_for function.

When we go to http://localhost:5000/static/style.css in the browser, we should see:

body {
    font-weight: bold;
}

displayed.

Rendering Templates

To render HTML output, we‘ve to render the content in a template.

To do that, we can use tyhe render_template function by writing:

app.py

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

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

templates/hello.html

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

We added a route that optionally takes the name parameter.

Then we call render_template with the path of the template in the templates folder.

Then we pass the variables we want to render into the subsequent arguments.

In hello.html , we check if the name variable is present, if it is, then we display the first message with the name ‘s value.

If we go to http://localhost:5000/hello/james, we see Hello james! displayed.

Otherwise, if we go to http://localhost:5000/hello, we see Hello, world.

Conclusion

We add static files and render templates with Flask.