Reputation: 4687
I am trying to perform some tests with calling route functions explicitly.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
myfunc()
return "Index!"
@app.route("/a")
def hello():
return "hello"
def myfunc():
with app.test_request_context('/', method='POST'):
app.hello()
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
But it fails with:
Traceback (most recent call last):
File "python2.7/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "python2.7/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "test.py", line 9, in index
myfunc()
File "test.py", line 18, in myfunc
app.hello()
AttributeError: 'Flask' object has no attribute 'hello'
Is it possible to test routing function by this way?
Yep example is a little bit ugly but I need to figure out what is wrong with it.
Upvotes: 0
Views: 4204
Reputation: 127390
To perform an "internal redirect", or call a view from another view, you push a new request context with the correct url and any other required data, then let Flask dispatch the request. You can return the value from the inner view, or your own response, in the outer view.
from flask import Flask, request, url_for
app = Flask(__name__)
@app.route('/')
def index():
with app.test_request_context(
url_for('hello'),
headers=request.headers.to_list(),
query_string=request.query_string
):
return app.dispatch_request()
@app.route('/greet')
def hello():
return 'Hello, {}!'.format(request.args.get('name', 'World'))
app.run()
Navigating to http://127.0.0.1/?name=davidism
returns Hello, davidism!
, the response from the hello
view.
You would not test views by calling them from a running application like this. To test a Flask application, you would use unit tests and the test client as described in the docs.
with app.test_client() as c:
r = c.get('/a')
assert r.data.decode() == 'hello'
Upvotes: 3
Reputation: 1723
hello is a regular function, decorating it with app.route won't add it to the app object. Did you perhaps mean to just invoke the hello function, like this:
with ...:
hello()
Upvotes: 0