Browse Source

url_for now supports no request context and no SERVER_NAME case

pull/1866/head
Jason Slay 9 years ago
parent
commit
e2daf87ab4
  1. 21
      flask/helpers.py
  2. 40
      tests/test_appctx.py

21
flask/helpers.py

@ -190,7 +190,24 @@ def make_response(*args):
return current_app.make_response(args)
def url_for(endpoint, **values):
def url_for(*args, **kwargs):
"""
wrapper based on https://github.com/miguelgrinberg/flack/blob/master/flack/utils.py
that also covers the case where application context exists with SERVER_NAME defined.
"""
reqctx = _request_ctx_stack.top
appctx = _app_ctx_stack.top
if reqctx is None and (appctx is None or appctx.url_adapter is None):
if kwargs.get('_external', False):
raise RuntimeError('Cannot generate external URLs without a '
'request context.')
with current_app.test_request_context():
return _url_for(*args, **kwargs)
return _url_for(*args, **kwargs)
def _url_for(endpoint, **values):
"""Generates a URL to the given endpoint with the method provided.
Variable arguments that are unknown to the target endpoint are appended
@ -294,11 +311,13 @@ def url_for(endpoint, **values):
# the URLs external by default.
else:
url_adapter = appctx.url_adapter
# Due to the new url_for wrapper, url_adapter will never be None here
if url_adapter is None:
raise RuntimeError('Application was not able to create a URL '
'adapter for request independent URL generation. '
'You might be able to fix this by setting '
'the SERVER_NAME config variable.')
external = values.pop('_external', True)
anchor = values.pop('_anchor', None)

40
tests/test_appctx.py

@ -16,7 +16,7 @@ import flask
def test_basic_url_generation():
app = flask.Flask(__name__)
app.config['SERVER_NAME'] = 'localhost'
app.config['SERVER_NAME'] = 'somehost'
app.config['PREFERRED_URL_SCHEME'] = 'https'
@app.route('/')
@ -25,13 +25,7 @@ def test_basic_url_generation():
with app.app_context():
rv = flask.url_for('index')
assert rv == 'https://localhost/'
def test_url_generation_requires_server_name():
app = flask.Flask(__name__)
with app.app_context():
with pytest.raises(RuntimeError):
flask.url_for('index')
assert rv == 'https://somehost/'
def test_url_generation_without_context_fails():
with pytest.raises(RuntimeError):
@ -49,6 +43,36 @@ def test_app_context_provides_current_app():
assert flask.current_app._get_current_object() == app
assert flask._app_ctx_stack.top is None
def test_url_for_without_server_name_or_app_context():
app = flask.Flask(__name__)
client = app.test_client()
@app.route('/endpoint')
def endpoint():
return 'Hello World!'
with app.app_context():
response = client.get(flask.url_for('endpoint', param='foo'))
assert response.status_code == 200
def test_get_with_arguments():
app = flask.Flask(__name__)
app.debug = True
@app.route('/echo')
def index():
assert 'key' in flask.request.args
return flask.jsonify( {'key': flask.request.args['key']} )
url = None
with app.test_request_context():
url = flask.url_for('index', key='test', _external=True)
assert url == 'http://localhost/echo?key=test'
rv = app.test_client().get(url)
assert b'"key": "test"' in rv.data
def test_app_tearing_down():
cleanup_stuff = []
app = flask.Flask(__name__)

Loading…
Cancel
Save