I have a few custom cli commands for a flask app I'm writing. I'm following the instructions here:
Command Line Interface
The problem is I do not want to put them all in my app.py file, it will get overbloated. What I would like to do is have my project structure:
project
|_ app.py
|_ cli.py
I thought about using a blueprint, but I get "Blueprint has no attribute 'cli'"
This is what I tried:
cli = Blueprint('cli', __name__) # I knew this would not work but I had to try
#cli.cli.command()
#click.argument('name')
def create_user(name):
print("hello")
Thanks
I would do something like this:
cli.py:
from flask import Flask
import click
def register_cli(app: Flask):
#app.cli.command()
#click.argument('name')
def create_user(name):
print("hello", name)
app.py:
from flask import Flask
from cli import register_cli
app = Flask(__name__)
register_cli(app)
It's common to create and configure (or just configure) app in factory functions.
Related
So I'm following a beginners tutorial on Flask and for whatever reason am getting an error on what is essentially the very first step.
I first created an "app" directory where I created a python file for "init.py" which contains the following code:
from flask import Flask
app = Flask(__name__)
from app import routes
I then created a "routes.py" python file in the same directory:
from app import app
#app.route('/')
#app.route('/index')
def index():
return "Hello, World!"
Finally (and this is where the problem stems from), I created a python file named "microblog.py" which is located in the same folder as the "app" directory:
from app import app
I then go to my virtual environment and run (using cmd windows):
set FLASK_APP=microblog.py
So far so good, however when I try to run the following code in cmd:
flask run
I get the following error:
ImportError: cannot import name 'app' from 'app' (C:\Users\Grae_\microblog\app\__init__.py)
If any further clarification is needed, here are my file locations:
C:\Users\Grae_\microblog
C:\Users\Grae_\microblog\app
C:\Users\Grae_\microblog\__init__.py
C:\Users\Grae_\microblog\routes.py
C:\Users\Grae_\microblog\venv
C:\Users\Grae_\microblog\microblog.py
Apologies if this is really obvious, I'm just obviously very new to Flask and have been stuck on this for a while.
Thanks
The issue here is on python package "app". The directory should have a file named __init__.py instead of init.py.
For example, you rename the file init.py to __init__.py and replace content with below code it should work
from flask import Flask
app = Flask(__name__)
def start():
from app import routes
start()
You can do something like this:-
test.py
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "Index!"
#app.route("/hello")
def hello():
return "Hello World!"
#app.route("/members")
def members():
return "Members"
#app.route("/members/<string:name>/")
def getMember(name):
return name</string:name>
if __name__ == "__main__":
app.run()
In command prompt, run the command-
python test.py
Try the URLs in your browser:
http://127.0.0.1:5000/
http://127.0.0.1:5000/hello
http://127.0.0.1:5000/members
http://127.0.0.1:5000/members/Karan/
I am using the standard flask app factoty setup as stated here:
http://flask.pocoo.org/docs/1.0/tutorial/factory/
flaskr/init.py
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
print('Hello World')
...
return app
I run this app with:
export FLASK_APP=flaskr
export FLASK_ENV=development
flask run
All very standard. But why is the code print("hello world") never executed?
edit
After reboot of my dev sytem the issue is gone. I am sorry I posted this.
Looks like you named the file init.py instead of __init__.py.
I guess you are using an older version of flask (<1.0).
The newest versions (>1.0) allow to detect automatically the function create_app or make_app (source code) to launch the application from CLI flask command.
You can update the flask package, for example with pip :
pip install --upgrade Flask
or add the following lines at the end of the __init__ file to create the application in an explicit way:
if __name__ == "__main__":
app = create_app()
app.run()
I wanted it to add common app-configuration options such as --config, --loglevel, --logfile, etc. to my flask.cli group and read them from the scriptinfo in my app factory function.
The #script_info_option decorator was apparently removed after 0.11 with a cryptic commit message like "implementing simplified interface".
So... how do I do add app-factory-time configuration options now?
Found out how you do it now:
Decorate your app factory with #click.pass_context so it gets the context as the first argument.
In the app factory, use ctx.find_root().params to get what was passed to the group.
You can create an app factory and pass arguments to it with the #pass_script_info decorator like so...
manage.py
#!/usr/bin/env python
import click
import config
from flask import Flask
from flask.cli import FlaskGroup, pass_script_info
def create_app(script_info):
app = Flask(__name__)
if script_info.config_mode:
obj = getattr(config, kwargs["config_mode"])
flask_config.from_object(obj)
...
return app
#click.group(cls=FlaskGroup, create_app=create_app)
#click.option('-m', '--config-mode', default="Development")
#pass_script_info
def manager(script_info, config_mode):
script_info.config_mode = config_mode
if __name__ == "__main__":
manager()
config.py
class Config(object):
TESTING = False
class Production(Config):
DATABASE_URI = 'mysql://user#localhost/foo'
class Development(Config):
DATABASE_URI = 'sqlite:///app.db'
class Testing(Config):
TESTING = True
DATABASE_URI = 'sqlite:///:memory:'
Now in the command line (after running pip install manage.py) you can do manage -m Production run.
I'm in the beginning stages of a Flask application. The problems I'm having is that whenever I attempt to run the application I get:
app/application/___init___.py, line 11 in <module>
from user_auth.views import auth
ImportError: No module named user_auth.views
I have no idea what the problem is. The import for the home.view did this as well, then it stopped and worked fine on the local server. Been trying to figure this out for the longest, there aren't that many moving parts in the application as of yet, so not sure why this is happeninng. File structure and code below:
|app
|-application
|--__ init __.py
|--home
|--user_auth
|----forms.py
|----views.py
|----templates
|----static
My application/__ init __.py file:
from flask import Flask
app = Flask(__name__)
app.config.from_object('_config')
from home.views import home
from user_auth.views import auth
app.register_blueprint(home)
app.register_blueprint(auth)
My application/user_auth/views.py
from flask import Blueprint
auth = Blueprint('auth', __name__,
url_prefix='/user_auth',
template_folder='templates',
static_folder='static')
You're missing an __init__.py file under ./user_auth/ to make user_auth a module.
There's more information about modules in the docs.
This is Flask app context
app = Flask(__name__)
with app.app_context():
# insert code here
Most of the use cases of app context involves having 'app' initialized on the same script or importing app from the base.
My application is structured as the following:
# application/__init__.py
def create_app(config):
app = Flask(__name__)
return app
# manage.py
from application import create_app
from flask_script import Manager
manager = Manager(create_app)
manager.add_command("debug", Server(host='0.0.0.0', port=7777))
This might be really trivial issue, but how I should call 'with app.app_context()' if my application is structured like this?
Flask-Script calls everything inside the test context, so you can use current_app and other idioms:
The Manager runs the command inside a Flask test context. This means that you can access request-local proxies where appropriate, such as current_app, which may be used by extensions.
http://flask-script.readthedocs.org/en/latest/#accessing-local-proxies
So you don't need to use with app.app_context() with Manager scripts. If you're trying to do something else, then you'd have to create the app first:
from application import create_app
app = create_app()
with app.app_context():
# stuff here