Table of Contents
Flask extensions
Flask extensions are packages that you can install to extend the capabilities of Flask. Their point is to provide a convenient and clear way to integrate packages into Flask. To see all the available extensions, visit https://flask.pocoo.org/extenstions/. The page has packages whose capabilities range from sending emails to creating full-fledged administrator interfaces. It’s important to keep in mind that you can extend Flask’s capabilities with more than just its extensions. In fact, any package from the standard Python or PyPi library will do. The rest of the tutorial is about how to install and integrate a handy extension for Flask called Flask-Script.
Flask-Script extension
Flask-Script is a handy miniature extension that allows you to create command line interfaces, run the Python server and console in the context of applications, make certain variables visible in the console automatically, and so on. It’s worth recalling what was discussed in the Flask Basics lesson. To run a development server on a particular host and port, you have to pass them as arguments-keywords to the run()
method:
if __name__ == "__main__":
app.run(debug=True, host="127.0.0.10", port=9000)
The problem is that this approach is not flexible. It is much more convenient to pass the host and port as command line parameters when starting the server. Flask-Script allows you to do this. You can install Flask-Script using pip:
(env) [email protected]:~/flask_app$ pip install flask-script
To use Flask-Script, you must first import the Manager
class from the flask_script
package and create an instance of the Manager
object by passing an application instance to it. In this way the Flask extensions are integrated. First you import the desired class from the package, and then create an instance by passing the application instance to it. You need to open the file main2.py
and modify it as follows:
from flask import Flask, render_template
from flask_script import Manager
app = Flask(__name__)
manager = Manager(app)
#...
The created Manager
object also has a run()
method, which in addition to running the development server can read command line arguments. You should replace the line app.run(debug=True)
to manager.run()
. At this point main2.py
should look like this:
from flask import flask, render_template
from flask_script import Manager
app = Flask(__name__)
manager = Manager(app)
@app.route('/')
def index():
return render_template('index.html', name='Jerry')
@app.route('/user/<int:user_id>/')
def user_profile(user_id):
return "Profile page of user #{}".format(user_id)
@app.route('/books/<genre>/')
def books(genre):
return "All Books in {} category".format(genre)
if __name__ == "__main__":
manager.run()
The application now has access to basic commands. To see which ones are available, run main2.py
:
(env) [email protected]:~/flask_app$ python main2.py
usage: main2.py [-?] {shell,runserver} ...
positional arguments:
{shell,runserver}
shell Runs a Python shell inside a Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
As the output shows, there are now only two commands: shell
and runserver
. Let’s start with the runserver
command. runserver
runs the web server. By default, it runs on 127.0.0.1 on port 5000. To see the options for any command, you need to type --help
and the command itself. For example:
(env) [email protected]:~/flask_app$ python main2.py runserver --help
usage: main2.py runserver [-?] [-h HOST] [-p PORT] [--threaded]
[--processes PROCESSES] [--passthrough-errors] [-d]
[-D] [-r] [-R] [--ssl-crt SSL_CRT]
[--ssl-key SSL_KEY]
Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
-h HOST, --host HOST
-p PORT, -port PORT
--threaded
--processes PROCESSES
--passthrough-errors
-d, --debug enable the Werkzeug debugger (DO NOT use in production
code)
-D, -no-debug disable the Werkzeug debugger
-r, -reload monitor Python files for changes (not 100% safe for
production use)
-R, --no-reload do not monitor Python files for changes
--ssl-crt SSL_CRT Path to ssl certificate
--ssl-key SSL_KEY Path to ssl key
The most widely used options for runserver
are --host
and --post
. You can use them to run a development server on a specific interface and port. For example:
(env) [email protected]:~/flask_app$ python main2.py runserver --host=127.0.0.2 --port 8000
* Running on http://127.0.0.2:8000/ (Press CTRL+C to quit)
By default, the runserver
command runs the server without a debugger. You can enable it manually as follows:
(env) [email protected]:~/flask_app$ python main2.py runserver -d -r
* Restarting with stat
* Debugger is active!
* Debugger PIN: 250-045-653
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
A simpler way to start the debugger is to select True
for the debug
attribute of the object(app
) instance. To do this, open main2.py
and modify the file as follows:
#...
app = Flask(__name__)
app.debug = True
manager = Manager(app)
#...
Next, about the shell
command. shell
runs the Python console in the context of the Flask application. This means that all objects within the application and request contexts will be available in the console without creating additional contexts. To start the console you need to enter the following command.
(env) [email protected]:~/flask_app$ python main2.py shell
Get access to certain objects.
>>>
>>> > from flask import current_app, url_for, request
>>>
>>> current_app.name
>> 'main2'
>>>
>>>
>>> url_for('user_profile', user_id=10)
"/user/10/
>>>
>>> > request.path
'/'
>>>
As expected, this can be done without creating application and query contexts.
Creating Commands
Once the Manager
instance has been created, you can start creating your own commands. There are two ways to do this:
- With the
Command
class - With
@command
decorator
Creating commands with the Command
class In the main2.py
file, add the Faker
class:
#...
from flask_script import Manager, Command
#...
manager = Manager(app)
class Faker(Command):
'Command to add fake data to tables'
def run(self):
# function logic
print("Fake data entered")
@app.route('/')
#...
The Faker
command was created by inheriting the Command
class. The run()
method is called when the command is executed. To execute a command through the command line, you need to add it to a Manager
instance using the add_command()
method:
#...
class Faker(Command):
'Command to add fake data to tables'
def run(self):
# function logic
print("Fake data entered")
manager.add_command('faker', Faker())
#...
Now you need to go back to the terminal again and run the file main2.py
:
(env) [email protected]:~/flask_app$ python main2.py
usage: main2.py [-?] {faker,shell,runserver} ...
positional arguments:
{faker,shell,runserver}
faker Command to add fake data to tables
shell Runs a Python shell inside Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
Note that there is now a faker
command in addition to shell
and runserver
. The description before the command itself is taken from the documentation line of the Faker
class. To run it, enter the following command:
(env) [email protected]:~/flask_app$ python main2.py faker
Fake data entered
Creating commands with the @command
decorator Creating commands using the Command
class is quite extensive. Alternatively, you can use the @command
decorator of an instance of the Manager
class. To do this, open file main2.py
and change it as follows:
#...
manager.add_command("faker", Faker())
@manager.command
def foo():
"This is the command that was created."
print("foo command executed")
@app.route('/')
#...
A simple foo
command was created that outputs foo command executed
when called. The @command
decorator automatically adds the command to an existing Manager
instance, so you don’t need to call the add_command()
method. To see how the commands are used, you need to go back to the terminal and run main2.py
.
(env) [email protected]:~/flask_app$ python main2.py
usage: main2.py [-?] {faker,foo,shell,runserver} ...
positional arguments:
{faker,foo,shell,runserver}
faker Command to add fake data to tables
foo This is a created command
shell Runs a Python shell inside a Flask application context.
runserver Runs the Flask development server i.e. app.run()
optional arguments:
-?, --help show this help message and exit
Since the foo
command is now available, you can execute it by entering the following command.
(env) [email protected]:~/flask_app$ python main2.py foo
foo command executed
Automatic import of objects
Importing a large number of objects on the command line can be tedious. With Flask-Script you can make objects visible in the terminal without explicitly importing them. The Shell
command launches a shell. The Shell
constructor function takes the argument-keyword make_context
. The argument passed to make_context
must be callable and return a dictionary. By default, the callable object returns a dictionary containing only an instance of the application, i.e., app
. This means that by default the shell can only access the application instance(app
) without specifically importing it. To change this behavior, you need to assign make_context
to a new call-supporting object (function). This will return a dictionary with the objects you want to access inside the shell. Let’s open the main2.py
file to add the following code after the foo()
function.
#...
from flask_script import Manager, Command, Shell
#...
def shell_context():
import os, sys
return dict(app=app, os=os, sys=sys)
manager.add_command("shell", Shell(make_context=shell_context))
#...
Here, the called shell_context()
function is passed the make_context
keyword argument. The shell_context
function returns a dictionary with three objects: app, os
, and sys
. As a result, these objects are now available inside the shell, even though they were not imported.
(env) [email protected]:~/flask_app$python main2.py shell
>>>
>>> app
<Flask 'main2'>
>>>
>>> os.name
'posix'
>>>
>>> sys.platform
'linux'
>>>
>>>