Browse Source

rewrite cli docs

reflects the current FLASK_APP detection
pull/2490/head
David Lord 7 years ago
parent
commit
9bc329c0c9
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
  1. 496
      docs/cli.rst
  2. 3
      docs/installation.rst
  3. 42
      flask/cli.py

496
docs/cli.rst

@ -1,145 +1,148 @@
.. currentmodule:: flask
.. _cli:
Command Line Interface
======================
.. versionadded:: 0.11
Installing Flask installs the ``flask`` script, a `Click`_ command line
interface, in your virtualenv. Executed from the terminal, this script gives
access to built-in, extension, and application-defined commands. The ``--help``
option will give more information about any commands and options.
.. currentmodule:: flask
.. _Click: http://click.pocoo.org/
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
-----------
Application Discovery
---------------------
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 ``flask`` command is installed by Flask, not your application; it must be
told where to find your application in order to use it. The ``FLASK_APP``
environment variable is used to specify how to load the application.
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.
Unix Bash (Linux, Mac, etc.)::
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.
$ export FLASK_APP=hello
$ flask run
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.
Windows CMD::
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.
> set FLASK_APP=hello
> flask run
Given a :file:`hello.py` file with the application in it named ``app``
this is how it can be run.
Windows PowerShell::
Environment variables (On Windows use ``set`` instead of ``export``)::
> $env:FLASK_APP = "hello"
> flask run
export FLASK_APP=hello
flask run
While ``FLASK_APP`` supports a variety of options for specifying your
application, most use cases should be simple. Here are the typical values:
Or with a filename::
(nothing)
The file :file:`wsgi.py` is imported, automatically detecting an app
(``app``). This provides an easy way to create an app from a factory with
extra arguments.
export FLASK_APP=/path/to/hello.py
flask run
``FLASK_APP=hello``
The name is imported, automatically detecting an app (``app``) or factory
(``create_app``).
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.
``FLASK_APP`` has three parts: an optional path that sets the current working
directory, a Python file or dotted import path, and an optional variable
name of the instance or factory. If the name is a factory, it can optionally
be followed by arguments in parentheses. The following values demonstrate these
parts:
Edit the activate script for the shell you use. For example:
``FLASK_APP=src/hello``
Sets the current working directory to ``src`` then imports ``hello``.
Unix Bash: ``venv/bin/activate``::
``FLASK_APP=hello.web``
Imports the path ``hello.web``.
FLASK_APP=hello
export FLASK_APP
``FLASK_APP=hello:app2``
Uses the ``app2`` Flask instance in ``hello``.
Windows CMD.exe: ``venv\Scripts\activate.bat``::
``FLASK_APP="hello:create_app('dev')"``
The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
as the argument.
set "FLASK_APP=hello"
:END
If ``FLASK_APP`` is not set, the command will look for a file called
:file:`wsgi.py` or :file:`app.py` and try to detect an application instance or
factory.
Debug Flag
----------
Within the given import, the command looks for an application instance named
``app`` or ``application``, then any application instance. If no instance is
found, the command looks for a factory function named ``create_app`` or
``make_app`` that returns an instance.
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::
When calling an application factory, if the factory takes an argument named
``info``, then the :class:`~cli.ScriptInfo` instance is passed as a keyword
argument. If parentheses follow the factory name, their contents are parsed
as Python literals and passes as arguments to the function. This means that
strings must still be in quotes.
export FLASK_DEBUG=1
Running a Shell
---------------
Run the Development Server
--------------------------
To run an interactive Python shell you can use the ``shell`` command::
The :func:`run <cli.run_command>` command will start the development server. It
replaces the :meth:`Flask.run` method in most cases. ::
flask shell
$ flask run
* Serving Flask app "hello"
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
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`.
.. warning:: Do not use this command to run your application in production.
Only use the development server during development. The development server
is provided for convenience, but is not designed to be particularly secure,
stable, or efficient. See :ref:`deployment` for how to run in production.
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__)
Open a Shell
------------
@app.cli.command()
def initdb():
"""Initialize the database."""
click.echo('Init the db')
To explore the data in your application, you can start an interactive Python
shell with the :func:`shell <cli.shell_command>` command. An application
context will be active, and the app instance will be imported. ::
The command will then show up on the command line::
$ flask shell
Python 3.6.2 (default, Jul 20 2017, 03:52:27)
[GCC 7.1.1 20170630] on linux
App: example
Instance: /home/user/Projects/hello/instance
>>>
$ flask initdb
Init the db
Use :meth:`~Flask.shell_context_processor` to add other automatic imports.
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.
Debug Mode
----------
It can also be disabled by passing ``with_appcontext=False`` to the
decorator::
Set the :envvar:`FLASK_DEBUG` environment variable to override the
application's :attr:`~Flask.debug` flag. The value ``1`` enables it, ``0``
disables it. Forcing the debug flag on also enables the debugger and reloader
when running the development server. ::
@app.cli.command(with_appcontext=False)
def example():
pass
$ FLASK_DEBUG=1 flask run
* Serving Flask app "hello"
* Forcing debug mode on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with inotify reloader
* Debugger is active!
* Debugger PIN: 223-456-919
.. _dotenv:
Loading Environment Variables From ``.env`` Files
-------------------------------------------------
Environment Variables From dotenv
---------------------------------
Rather than setting ``FLASK_APP`` each time you open a new terminal, you can
use Flask's dotenv support to set environment variables automatically.
If `python-dotenv`_ is installed, running the :command:`flask` command will set
If `python-dotenv`_ is installed, running the ``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
@ -150,186 +153,231 @@ 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`
Directories are scanned upwards from the directory you call ``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.
The files are only loaded by the ``flask`` command or calling
:meth:`~Flask.run`. If you would like to load these files when running in
production, you should call :func:`~cli.load_dotenv` manually.
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
Factory Functions
-----------------
Environment Variables From virtualenv
-------------------------------------
If you do not want to install dotenv support, you can still set environment
variables by adding them to the end of the virtualenv's :file:`activate`
script. Activating the virtualenv will set the variables.
Unix Bash, :file:`venv/bin/activate`::
export FLASK_APP=hello
Windows CMD, :file:`venv\Scripts\activate.bat`::
set FLASK_APP=hello
It is preferred to use dotenv support over this, since :file:`.flaskenv` can be
committed to the repository so that it works automatically wherever the project
is checked out.
Custom Commands
---------------
The ``flask`` command is implemented using `Click`_. See that project's
documentation for full information about writing commands.
This example adds the command ``create_user`` that takes the argument
``name``. ::
import click
from flask import Flask
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.
app = Flask(__name__)
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.
@app.cli.command()
@click.argument('name')
def create_user(name):
...
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'])
flask create_user admin
Once this has happened you can make the :command:`flask` command automatically
pick it up::
This example adds the same command, but as ``user create``, a command in a
group. This is useful if you want to organize multiple related commands. ::
export YOURAPPLICATION_CONFIG=/path/to/config.cfg
export FLASK_APP=/path/to/autoapp.py
import click
from flask import Flask
from flask.cli import AppGroup
app = Flask(__name__)
user_cli = AppGroup('user')
@user_cli.command('create')
@click.argument('name')
def create_user(name):
...
app.cli.add_command(user_cli)
::
flask user create demo
Application Context
~~~~~~~~~~~~~~~~~~~
Commands added using the Flask app's :attr:`~Flask.cli`
:meth:`~cli.AppGroup.command` decorator will be executed with an application
context pushed, so your command and extensions have access to the app and its
configuration. If you create a command using the Click :func:`~click.command`
decorator instead of the Flask decorator, you can use
:func:`~cli.with_appcontext` to get the same behavior. ::
import click
from flask.cli import with_appcontext
@click.command
@with_appcontext
def do_work():
...
app.cli.add_command(do_work)
If you're sure a command doesn't need the context, you can disable it::
@app.cli.command(with_appcontext=False)
def do_work():
...
Plugins
-------
Flask will automatically load commands specified in the ``flask.commands``
`entry point`_. This is useful for extensions that want to add commands when
they are installed. Entry points are specified in :file:`setup.py` ::
from setuptools import setup
setup(
name='flask-my-extension',
...,
entry_points={
'flask.commands': [
'my-command=flask_my_extension.commands:cli'
],
},
)
.. _entry point: https://packaging.python.org/tutorials/distributing-packages/#entry-points
Inside :file:`flask_my_extension/commands.py` you can then export a Click
object::
import click
@click.command()
def cli():
...
Once that package is installed in the same virtualenv as your Flask project,
you can run ``flask my-command`` to invoke the command.
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
When you are using the app factory pattern, it may be more convenient to define
your own Click script. Instead of using ``FLASK_APP`` and letting Flask load
your application, you can create your own Click object and export it as a
`console script`_ entry point.
Create an instance of :class:`~cli.FlaskGroup` and pass it the factory::
import click
from flask import Flask
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'))
def create_app():
app = Flask('wiki')
# other setup
return app
@click.group(cls=FlaskGroup, create_app=create_wiki_app)
@click.group(cls=FlaskGroup, create_app=create_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`::
"""Management script for the Wiki application."""
Define the entry point in :file:`setup.py`::
from setuptools import setup
setup(
name='flask-my-extension',
...
entry_points='''
[flask.commands]
my-command=mypackage.commands:cli
''',
...,
entry_points={
'console_scripts': [
'wiki=wiki:cli'
],
},
)
Inside :file:`mypackage/commands.py` you can then export a Click object::
Install the application in the virtualenv in editable mode and the custom
script is available. Note that you don't need to set ``FLASK_APP``. ::
import click
$ pip install -e .
$ wiki run
@click.command()
def cli():
"""This is an example command."""
.. _console script: https://packaging.python.org/tutorials/distributing-packages/#console-scripts
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.
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. These instructions
should be similar for any other IDE you might want to use.
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:
In PyCharm, 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.
There's quite a few options to change, but 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 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.
For the *Script* input (**A**), navigate to your project's virtual environment.
Within that folder, pick the ``flask`` executable which will reside in the
``bin`` folder, or in the ``Scripts`` 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.
The *Script Parameter* field (**B**) is set to the CLI command you to execute.
In this example we use ``run``, which will run the 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).
You can skip this next step if you're using :ref:`dotenv`. 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.
our application file or package resides. PyCharm changed it to the directory
with the ``flask`` executable when we selected it earlier, which is incorrect.
Finally, untick the *PYTHONPATH* options (**E**) and give the configuration a
good descriptive name, such as “Run Flask Server” and click *Apply*.
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``.
Now that we have a configuration which runs ``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``.

3
docs/installation.rst

@ -43,10 +43,13 @@ use them if you install them.
installed.
* `python-dotenv`_ enables support for :ref:`dotenv` when running ``flask``
commands.
* `Watchdog`_ provides a faster, more efficient reloader for the development
server.
.. _Blinker: https://pythonhosted.org/blinker/
.. _SimpleJSON: https://simplejson.readthedocs.io/
.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
.. _watchdog: https://pythonhosted.org/watchdog/
Virtual environments
--------------------

42
flask/cli.py

@ -234,11 +234,16 @@ def get_version(ctx, param, value):
}, color=ctx.color)
ctx.exit()
version_option = click.Option(['--version'],
help='Show the flask version',
expose_value=False,
callback=get_version,
is_flag=True, is_eager=True)
version_option = click.Option(
['--version'],
help='Show the flask version',
expose_value=False,
callback=get_version,
is_flag=True,
is_eager=True
)
class DispatchingApp(object):
"""Special application that dispatches to a Flask application which
@ -713,24 +718,21 @@ def routes_command(sort, all_methods):
cli = FlaskGroup(help="""\
This shell command acts as general utility script for Flask applications.
It loads the application configured (through the FLASK_APP environment
variable) and then provides commands either provided by the application or
Flask itself.
The most useful commands are the "run" and "shell" command.
A general utility script for Flask applications.
Example usage:
Provides commands from Flask, extensions, and the application. Loads the
application defined in the FLASK_APP environment variable, or from a wsgi.py
file. Debug mode can be controlled with the FLASK_DEBUG
environment variable.
\b
%(prefix)s%(cmd)s FLASK_APP=hello.py
%(prefix)s%(cmd)s FLASK_DEBUG=1
%(prefix)sflask run
""" % {
'cmd': os.name == 'posix' and 'export' or 'set',
'prefix': os.name == 'posix' and '$ ' or '',
})
{prefix}{cmd} FLASK_APP=hello.py
{prefix}{cmd} FLASK_DEBUG=1
{prefix}flask run
""".format(
cmd='export' if os.name == 'posix' else 'set',
prefix='$ ' if os.name == 'posix' else '> '
))
def main(as_module=False):

Loading…
Cancel
Save