You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

335 lines
12 KiB

.. _cli:
Command Line Interface
======================
.. versionadded:: 0.11
.. currentmodule:: flask
One of the nice new features in Flask 0.11 is the built-in integration of
the `click <http://click.pocoo.org/>`_ command line interface. This
enables a wide range of new features for the Flask ecosystem and your own
applications.
Basic Usage
-----------
After installation of Flask you will now find a :command:`flask` script
installed into your virtualenv. If you don't want to install Flask or you
have a special use-case you can also use ``python -m flask`` to accomplish
exactly the same.
The way this script works is by providing access to all the commands on
your Flask application's :attr:`Flask.cli` instance as well as some
built-in commands that are always there. Flask extensions can also
register more commands there if they desire so.
For the :command:`flask` script to work, an application needs to be discovered.
Flask looks for a module named :file:`wsgi.py` or :file:`app.py` by default,
and if it finds one it assumes the application is defined in it.
You can instruct Flask to look for the application in a different module by
exporting the ``FLASK_APP`` environment variable. It can be either set to an
import path or to a filename of a Python module that contains a Flask
application.
In that imported file the name of the app needs to be called ``app`` or
optionally be specified after a colon. For instance
``mymodule:application`` would tell it to use the `application` object in
the :file:`mymodule.py` file.
Given a :file:`hello.py` file with the application in it named ``app``
this is how it can be run.
Environment variables (On Windows use ``set`` instead of ``export``)::
export FLASK_APP=hello
flask run
Or with a filename::
export FLASK_APP=/path/to/hello.py
flask run
Virtualenv Integration
----------------------
If you are constantly working with a virtualenv you can also put the
``export FLASK_APP`` into your ``activate`` script by adding it to the
bottom of the file. That way every time you activate your virtualenv you
automatically also activate the correct application name.
Edit the activate script for the shell you use. For example:
Unix Bash: ``venv/bin/activate``::
FLASK_APP=hello
export FLASK_APP
Windows CMD.exe: ``venv\Scripts\activate.bat``::
set "FLASK_APP=hello"
:END
Debug Flag
----------
The :command:`flask` script can also be instructed to enable the debug
mode of the application automatically by exporting ``FLASK_DEBUG``. If
set to ``1`` debug is enabled or ``0`` disables it::
export FLASK_DEBUG=1
Running a Shell
---------------
To run an interactive Python shell you can use the ``shell`` command::
flask shell
This will start up an interactive Python shell, setup the correct
application context and setup the local variables in the shell. This is
done by invoking the :meth:`Flask.make_shell_context` method of the
application. By default you have access to your ``app`` and :data:`g`.
Custom Commands
---------------
If you want to add more commands to the shell script you can do this
easily. For instance if you want a shell command to initialize the database you
can do this::
import click
from flask import Flask
app = Flask(__name__)
@app.cli.command()
def initdb():
"""Initialize the database."""
click.echo('Init the db')
The command will then show up on the command line::
$ flask initdb
Init the db
Application Context
-------------------
Most commands operate on the application so it makes a lot of sense if
they have the application context setup. Because of this, if you register
a callback on ``app.cli`` with the :meth:`~flask.cli.AppGroup.command` the
callback will automatically be wrapped through :func:`cli.with_appcontext`
which informs the cli system to ensure that an application context is set
up. This behavior is not available if a command is added later with
:func:`~click.Group.add_command` or through other means.
It can also be disabled by passing ``with_appcontext=False`` to the
decorator::
@app.cli.command(with_appcontext=False)
def example():
pass
.. _dotenv:
Loading Environment Variables From ``.env`` Files
-------------------------------------------------
If `python-dotenv`_ is installed, running the :command:`flask` command will set
environment variables defined in the files :file:`.env` and :file:`.flaskenv`.
This can be used to avoid having to set ``FLASK_APP`` manually every time you
open a new terminal, and to set configuration using environment variables
similar to how some deployment services work.
Variables set on the command line are used over those set in :file:`.env`,
which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
used for public variables, such as ``FLASK_APP``, while :file:`.env` should not
be committed to your repository so that it can set private variables.
Directories are scanned upwards from the directory you call :command:`flask`
from to locate the files. The current working directory will be set to the
location of the file, with the assumption that that is the top level project
directory.
The files are only loaded by the :command:`flask` command or calling
:meth:`~flask.Flask.run`. If you would like to load these files when running in
production, you should call :func:`~flask.cli.load_dotenv` manually.
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
Factory Functions
-----------------
In case you are using factory functions to create your application (see
:ref:`app-factories`) you will discover that the :command:`flask` command
cannot work with them directly. Flask won't be able to figure out how to
instantiate your application properly by itself. Because of this reason
the recommendation is to create a separate file that instantiates
applications. This is not the only way to make this work. Another is the
:ref:`custom-scripts` support.
For instance if you have a factory function that creates an application
from a filename you could make a separate file that creates such an
application from an environment variable.
This could be a file named :file:`autoapp.py` with these contents::
import os
from yourapplication import create_app
app = create_app(os.environ['YOURAPPLICATION_CONFIG'])
Once this has happened you can make the :command:`flask` command automatically
pick it up::
export YOURAPPLICATION_CONFIG=/path/to/config.cfg
export FLASK_APP=/path/to/autoapp.py
From this point onwards :command:`flask` will find your application.
.. _custom-scripts:
Custom Scripts
--------------
While the most common way is to use the :command:`flask` command, you can
also make your own "driver scripts". Since Flask uses click for the
scripts there is no reason you cannot hook these scripts into any click
application. There is one big caveat and that is, that commands
registered to :attr:`Flask.cli` will expect to be (indirectly at least)
launched from a :class:`flask.cli.FlaskGroup` click group. This is
necessary so that the commands know which Flask application they have to
work with.
To understand why you might want custom scripts you need to understand how
click finds and executes the Flask application. If you use the
:command:`flask` script you specify the application to work with on the
command line or environment variable as an import name. This is simple
but it has some limitations. Primarily it does not work with application
factory functions (see :ref:`app-factories`).
With a custom script you don't have this problem as you can fully
customize how the application will be created. This is very useful if you
write reusable applications that you want to ship to users and they should
be presented with a custom management script.
To explain all of this, here is an example :file:`manage.py` script that
manages a hypothetical wiki application. We will go through the details
afterwards::
import os
import click
from flask.cli import FlaskGroup
def create_wiki_app(info):
from yourwiki import create_app
return create_app(
config=os.environ.get('WIKI_CONFIG', 'wikiconfig.py'))
@click.group(cls=FlaskGroup, create_app=create_wiki_app)
def cli():
"""This is a management script for the wiki application."""
if __name__ == '__main__':
cli()
That's a lot of code for not much, so let's go through all parts step by
step.
1. First we import the ``click`` library as well as the click extensions
from the ``flask.cli`` package. Primarily we are here interested
in the :class:`~flask.cli.FlaskGroup` click group.
2. The next thing we do is defining a function that is invoked with the
script info object (:class:`~flask.cli.ScriptInfo`) from Flask and its
purpose is to fully import and create the application. This can
either directly import an application object or create it (see
:ref:`app-factories`). In this case we load the config from an
environment variable.
3. Next step is to create a :class:`FlaskGroup`. In this case we just
make an empty function with a help doc string that just does nothing
and then pass the ``create_wiki_app`` function as a factory function.
Whenever click now needs to operate on a Flask application it will
call that function with the script info and ask for it to be created.
4. All is rounded up by invoking the script.
CLI Plugins
-----------
Flask extensions can always patch the :attr:`Flask.cli` instance with more
commands if they want. However there is a second way to add CLI plugins
to Flask which is through ``setuptools``. If you make a Python package that
should export a Flask command line plugin you can ship a :file:`setup.py` file
that declares an entrypoint that points to a click command:
Example :file:`setup.py`::
from setuptools import setup
setup(
name='flask-my-extension',
...
entry_points='''
[flask.commands]
my-command=mypackage.commands:cli
''',
)
Inside :file:`mypackage/commands.py` you can then export a Click object::
import click
@click.command()
def cli():
"""This is an example command."""
Once that package is installed in the same virtualenv as Flask itself you
can run ``flask my-command`` to invoke your command. This is useful to
provide extra functionality that Flask itself cannot ship.
PyCharm Integration
-------------------
The new Flask CLI features aren’t yet fully integrated into the PyCharm IDE,
so we have to do a few tweaks to get them working smoothly.
In your PyCharm application, with your project open, click on *Run*
from the menu bar and go to *Edit Configurations*. You’ll be greeted by a
screen similar to this:
.. image:: _static/pycharm-runconfig.png
:align: center
:class: screenshot
:alt: screenshot of pycharm's run configuration settings
There’s quite a few options to change, but don’t worry— once we’ve done it
for one command, we can easily copy the entire configuration and make a
single tweak to give us access to other flask cli commands, including
any custom ones you may implement yourself.
For the *Script* input (**A**), we want to navigate to the virtual environment
we’re using for our project and within that folder we want to pick the ``flask``
file which will reside in the ``bin`` folder, or in the ``Scripts`` folder if
you're on Windows.
The *Script Parameter* field (**B**) is set to the cli command you wish to
execute, in this example we use ``run`` which will run our development server.
We need to add an environment variable (**C**) to identify our application.
Click on the browse button and add an entry with ``FLASK_APP`` on the
left and the name of the python file, or package on the right
(``app.py`` for example).
Next we need to set the working directory (**D**) to be the same folder where
our application file or package resides.
Finally, untick the *PYTHONPATH* options (**E**) and give the configuration a
good descriptive name, such as “Run Flask Server” and click *Apply*.
Now that we have on run configuration which implements ``flask run`` from within
PyCharm, we can simply copy that configuration and alter the script argument
to run a different cli command, e.g. ``flask shell``.