1

When following tutorials the @ask decorator works when it is in the same file as ask = Ask(app, "/someroute") and after app = Flask(name). If I wish to put the @ask decorators in a view file in its own folder, using Blueprints no matter what I try I get "name 'ask' is not defined" with the decorator

I should say I am new to flask, but have now got a base app working with things like flask-principal working with flask-login and flask-navigation able to display menu items only if permitted.

I have been following the many flask-ask tutorials and everything works (so far), but I would prefer to have the view code in a separate views.py in its own folder and use Blueprints. I using create_app(config_name) instead of app = Flask(name) as suggested in many flask tutorials. I wish to do this as I want to keep my main __init__.py as clean as possible.

My newness to flask prevents me from doing something like using the alexa-skills-kit-sdk-for-python in flask as suggested by some people on Gitter (as flask-ask doesn't seem to be maintained anymore) and I still don't understand flask enough to work out why the ask object is not available in a separate views.py

In all truth I am tempted just to have everything in app/__init__.py as this is only a hobby app, but I am trying to structure my flask apps as suggested by many blogs, i.e. if there is no obvious fix for this then I will resort to the way that works, but I can't help feeling this is something I have done wrong from a flask perspective not flask-ask.

It may be worth adding that I had some install problems (choking on PyYAML, so I downloaded the package and manually installed the requirements then run setup.py (just in case that had an impact on the issue)

#app/__init__.py
#Pytho 3

from flask_ask import Ask, statement, question, session

....

def create_app(config_name):
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_object(app_config[config_name])
    app.config.from_pyfile('config.py')

    Bootstrap(app)
    db.init_app(app)
    nav.init_app(app)
    toolbar.init_app(app)

    login_manager.init_app(app)
    login_manager.login_message = "You must be logged in to access this page."
    login_manager.login_view = "auth.login"    

    principals = Principal(app)

    ask = Ask(app, "/alexa")
    ask.init_app(app) #have also done it without this as some of the tutorials don't mention it

    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint)

    from .home import home as home_blueprint
    app.register_blueprint(home_blueprint)

    from .alexa import alexa as alexa_blueprint
    app.register_blueprint(alexa_blueprint,url_prefix='/alexa')



    # This loads fine 
    @ask.launch
    def start_skill():
        welcome_message = 'Hello there, would you like the news?'
        return question(welcome_message)

If I remove the @ask decorator code and put it as below....

#app/alexa/views.py
from flask_ask import Ask, statement, question, session
import json
import requests
import time
import unidecode

from . import alexa

    @alexa.route('/')
    def alexa_route():
     return('alexa')

    #this doesn't work
    @ask.launch # this is on line 33 (as below error)
    def start_skill():
        welcome_message = 'Hello there, would you like the news?'
        return question(welcome_message)

I get (I am using venv so the paths are to a virtual environment)

File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 2309, in call return self.wsgi_app(environ, start_response) File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 2295, in wsgi_app response = self.handle_exception(e) File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 1741, in handle_exception reraise(exc_type, exc_value, tb) File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise raise value File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise raise value File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/Users/username/Documents/Personal/Pi/template/lib/python3.7/site-packages/flask_debugtoolbar/init.py", line 125, in dispatch_request return view_func(**req.view_args) File "/Users/username/Documents/Personal/Pi/baseapp/app/alexa/views.py", line 33, in alexa_route return(ask) NameError: name 'ask' is not defined

Simon F
  • 41
  • 4

1 Answers1

1

When using flask's app-factory, you should create the module's object outside of create_app :

#my_app/__init__.py

from flask_ask import Ask, statement, question, session
...
ask = Ask()

def create_app(config_name):
    app = Flask(...)
    ...

    ask.init_app(app)

Then you can import the object whenever you need it :

#my_app/alexa/views.py
from my_app import ask
...

@ask.launch
def start_skill():
    welcome_message = 'Hello there, would you like the news?'
    return question(welcome_message)

Beware of naming your app "app" as this can be confusing. I took the freedom to change it to 'my_app' for more clarity.

Roch
  • 94
  • 6