Getting Started with the Flask CLI
The Flask Command Line Interface (CLI) provides a powerful way to manage your application, from running a development server to executing custom maintenance tasks. This system is built on top of the click library and uses the FlaskGroup class to integrate your application with the terminal.
By the end of this tutorial, you will be able to run your application using the built-in flask command, add your own custom commands, and create a standalone management script.
Prerequisites
To follow this tutorial, you need the following:
- Flask installed in your environment.
- (Optional)
python-dotenvinstalled if you want to use.envor.flaskenvfiles for configuration.
Step 1: Create a Basic Application
First, create a file named app.py. This file will serve as the entry point for the CLI.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello, Flask CLI!"
By naming your file app.py, the flask command will automatically find it without extra configuration.
Step 2: Use Built-in Commands
The flask command comes with several built-in utilities provided by FlaskGroup. Open your terminal and try the following:
Run the Development Server
flask run
This starts the development server. Under the hood, FlaskGroup adds the run_command to the CLI.
Inspect Routes
flask routes
This command, implemented as routes_command in src/flask/cli.py, lists all registered endpoints and their methods.
Interactive Shell
flask shell
The shell_command opens an interactive Python session. FlaskGroup automatically pushes an application context, so you can access the app object and current_app immediately.
Step 3: Add Custom Commands
You can extend the CLI by adding your own commands using the @app.cli.command decorator. Update your app.py:
import click
from flask import Flask
app = Flask(__name__)
@app.cli.command("hello")
@click.option("--name", default="World")
def hello_command(name):
"""A simple custom command."""
click.echo(f"Hello, {name}!")
Now, run your new command from the terminal:
flask hello --name Developer
When you register a command via app.cli.command, Flask automatically wraps it in an application context. This means you can access database connections or configuration without manually calling app.app_context().
Step 4: Create a Custom Management Script
For advanced use cases, you might want to create a standalone script that behaves like the flask command but is tailored to your project. You can do this by using FlaskGroup directly.
Create a file named manage.py:
import click
from flask import Flask
from flask.cli import FlaskGroup
def create_my_app():
app = Flask("my_management_app")
# Additional configuration here
return app
@click.group(cls=FlaskGroup, create_app=create_my_app)
def cli():
"""Management script for my application."""
pass
if __name__ == "__main__":
cli()
In this example:
FlaskGroup: We pass this class as theclsargument to the@click.groupdecorator. This tells Click to use Flask's specialized group logic, which handles loading the app and environment variables.create_app: We provide a factory function.FlaskGroupwill call this when it needs to load the application to run commands.ScriptInfo: Internally,FlaskGroupuses aScriptInfoobject to track the state of the application loading process.
You can now run this script directly:
python manage.py run
python manage.py shell
Important Considerations
- The
__main__Guard: Always wrapapp.run()in anif __name__ == "__main__":block. When you run theflaskcommand, it sets an environment variableFLASK_RUN_FROM_CLI="true". Ifapp.run()is called during import, it can interfere with the CLI's ability to execute commands. - Environment Variables: You can control the CLI behavior using environment variables like
FLASK_APP(to point to a specific file or factory) andFLASK_DEBUG(to enable debug mode). - Context Management:
FlaskGroupensures that an application context is active for any command that needs it. If you are writing a command that doesn't need the app (like a version check), you can use a standard@click.commandinstead of@app.cli.command.