Flask Series: Deployment

I will describe a setup with nginx as a web server. A web server cannot communicate directly with Flask, that’s why gunicorn will be used to act as a medium between the web server and the Flask application. Gunicorn is like application web server that will be running behind nginx, it is WSGI compatible. It can communicate with applications that support WSGI – Flask, Django.

Install the needed bits.

sudo apt-get update
sudo apt-get install -y python python-pip nginx gunicorn

Create a directory to store the project

sudo mkdir /home/www && cd /home/www

Download the project from the GitHub repository and copy the application to the /home/www directory.

git clone https://github.com/damyanbogoev/flask-bookshelf.git /tmp/
cd /tmp/flask-bookshelf
cp -r ./* /home/www/

Install the application requirements:

pip install -r requirements.txt

Configure nginx

sudo /etc/init.d/nginx start

sudo rm /etc/nginx/sites-enabled/default

sudo touch /etc/nginx/sites-available/flask_bookshelf

sudo ln -s /etc/nginx/sites-available/flask_bookshelf /etc/nginx/sites-enabled/flask_bookshelf

sudo vim /etc/nginx/sites-enabled/flask_bookshelf

The gunicorn will use port 8000 and handle the incoming HTTP requests.

You could add a separate configuration for the static files of the Flask application, because it is better to be served directly by nginx.

Restart the nginx to load the later configuration changes:

sudo /etc/init.d/nginx restart

Run the gunicorn on port 8000

/home/www/flask_bookshelf/

gunicorn --bind 0.0.0.0:8000 run:app

Start a new browser instance and navigate to

http://server_address

The complete demo application, described in this blog post, can be found here.

Flask Series: Internationalization

Internationalization (i18n) enables applications and services to support multiple languages and locales. Localization (L10n) adds support for a given language and locale.

The Flask-Babel extension adds support for i18n and L10n in a Flask application. It is built based on babel, pytz and speaklater.

Flask-Babel is easy to install and configure:

pip install Flask-Babel

bookshelf/config.py

SUPPORTED_LANGUAGES – dictionary stores information about the available languages, that are supported in the application.
BABEL_DEFAULT_LOCALE – default locale to use if no locale selector is registered, default is ‘en‘.
BABEL_DEFAULT_TIMEZONE – timezone to use for user facing dates, default is ‘UTC‘.

bookshelf/babel.cfg

The babel.cfg is a mapping file, intended to be used with the pybabel command line tool. It contains configuration data for Babel to tell where to look for texts – supported files, paths, etc.

Now that you have the Flask-Babel extensions installed and configured, you should provide the babel extension with locale and timezone information. It will call localeselector and timezoneselector functions to retrieve this information, if no data is returned (None) Flask-Babel will use the default settings from the configuration.

bookshelf/__init__.py

Several callback functions are used for managing the currently used language. The url_defaults() callback function set_language_code is used to inject values into a call for url_for() automatically.

bookshelf/__init__.py

The url_value_preprocessor() registers the get_lang_code() function, which obtains and sets the language code from the request on the application globals flask.g object.

bookshelf/__init__.py

The before_request ensure_lang_support function executes before each request and it is helpful to verify if the provided language is supported by the application.

bookshelf/__init__.py

Flask allows developers to register blueprints multiple times with different URLs, which can be used to add i18n support:

bookshelf/__init__.py

The next step is to mark all of the strings for translation, by wrapping them either in gettext() or in _() function calls:

Before

After

Once marked for translation, the texts should be extracted:

pybabel extract -F bookshelf/babel.cfg -o bookshelf/messages.pot bookshelf

To create a translation for a given language run the following command:

pybabel init -i bookshelf/messages.pot -d bookshelf/translations -l bg

where the pybabel init command writes a new (bg) language catalog in the bookshelf/translations directory for the extracted data from the bookshelf/messages.pot file. The command will create a new bookshelf/translations/bg/LC_MESSAGES folder and a new messages.po file inside. The messages.po file is used by the _() and gettext() function calls. You could use the poedit translation application to translate the strings accordingly.

When the translations are done, they should be compiled:

pybabel compile -d bookshelf/translations

The complete demo application, described in this blog post, can be found here.

In the next blog post I will describe how to deploy your Flask application.