Categories
Flask

Python Web Development with Flask — Favicon, Background Tasks, and HTTP Method Overrides

Spread the love

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.

Favicon

We can add a favicon by putting it in the static folder and then referencing it.

For example, we can write:

app.py

from flask import send_from_directory, Flask, render_template
import os

app = Flask(__name__)

@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'),
                               'favicon.ico', mimetype='image/vnd.microsoft.icon')

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

templates/index.html

<link rel="shortcut icon"
    href="{{ url_for('static', filename='favicon.ico') }}">
<p>hello world</p>

Then we put our favicon.ico file into the static folder.

Now we should see the favicon displayed in our browser’s tab.

Deferred Request Callbacks

We can add callbacks that are called before or after the current request.

For example, we can write:

from flask import Flask

app = Flask(__name__)

@app.before_request
def before_request():
    print('before called')

@app.after_request
def after_request(response):
    print('after called')
    return response

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

We call the @app.before_request to add a callback that’s run before a request is made.

The @app.after_request decorator lets us add a callback that’s run after a request is made.

The response parameter has the response that we return.

HTTP Method Overrides

We can add HTTP method overrides with our own class.

For example, we can write:

from flask import Flask

class HTTPMethodOverrideMiddleware(object):
    allowed_methods = frozenset([
        'GET',
        'HEAD',
        'POST',
        'DELETE',
        'PUT',
        'PATCH',
        'OPTIONS'
    ])
    bodyless_methods = frozenset(['GET', 'HEAD', 'OPTIONS', 'DELETE'])

    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper()
        if method in self.allowed_methods:
            environ['REQUEST_METHOD'] = method
        if method in self.bodyless_methods:
            environ['CONTENT_LENGTH'] = '0'
        return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

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

to add the HTTPMethodOverrideMiddleware class.

It has the allowed_methods variable to let us set the kinds of HTTP requests that can be made.

bodyless_methods has the types of HTTP requests that doesn’t require a request body.

The __call__ method lets us set the REQUEST_METHOD and the CONTENT_LENGTH request headers and return the request with the changes.

Then we add the override with:

app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

Celery Background Tasks

We can add background tasks in our app with Celery.

To use it, we run:

pip install celery redis

Then we can use it by writing:

from flask import Flask
from celery import Celery

def make_celery(app):
    celery = Celery(
        app.import_name,
        backend=app.config['CELERY_RESULT_BACKEND'],
        broker=app.config['CELERY_BROKER_URL']
    )

    class ContextTask(celery.Task):
        def __call__(self, *args, **kwargs):
            with app.app_context():
                return self.run(*args, **kwargs)

    celery.Task = ContextTask
    return celery

app = Flask(__name__)
app.config.update(
    CELERY_BROKER_URL='redis://localhost:6379',
    CELERY_RESULT_BACKEND='redis://localhost:6379'
)
celery = make_celery(app)

@celery.task()
def add_together(a, b):
    return a + b

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

We have the make_celery function that creates the Celery instance to let us connect to Redis.

Then we set the config with app.config.update .

And then we call make_celery to create the Celery object.

Then we can use the celery object to run our worker and create a Celery task with the @celery.task decorator.

Once we did that and started Redis, we can run:

result = add_together.delay(23, 42)
print(result.wait())

to run the task.

Conclusion

We can add favicons, request callbacks, and background tasks with Flask.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *