Flask url_for require application and request context to work.
from flask import url_forurl = url_for('page', page_number=2)
Most of the time I will work fine in request routing and rendering, but you might bump into the following error in specific use cases.
Without application context, you will bump into
RuntimeError: Attempted to generate a URL without the application context being pushed. This has to be executed when application context is available.
If application context is not available, you can create an application context.
app = Flask(__name__)with app.app_context(): url = url_for('page', page_number=2)
Without request context, you will bump into
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.
If request context is not available, you can create a test request context.
app = Flask(__name__)with app.test_request_context(): url = url_for('page', page_number=2)
NOTE: You can use SERVER_NAME
configuration to solve this as well, but it will affect the routing as well.
If both application and request context is not available.
app = Flask(__name__)with app.app_context(), app.test_request_context(): url = url_for('page', page_number=2)
_external=True parameter
url_for('page', page_number=2)
will produce a relative path, e.g. /page/2
.
For abosulte path, use url_for('page', page_number=2, _external=True)
, e.g. https://www.mydomain.com/page/2
If you use app.test_request_context
with _external=True
, it will always use http://localhost
as the domain name. The localhost
domain name is hardcoded, since it's a context for testing.
app = Flask(__name__)with app.app_context(), app.test_request_context(): # http://localhost/page/2 url = url_for('page', page_number=2, _external=True)
You can override the domain with test_request_context
's base_url
parameter.
with app.app_context(), app.test_request_context(base_url='https://www.mydomain.com'): # https://www.mydomain.com/page/2 url = url_for('page', page_number=2, _external=True)
You can now create your own url_for
function.
def safe_url_for_external(*args, **kwargs): with app.app_context(), app.test_request_context(base_url=kwargs['_base_url']): del kwargs['_base_url'] kwargs['_external'] = True return url_for(*args, **kwargs)# https://www.mydomain.com/page/2url = safe_url_for_external('page', page_number=2, _base_url='https://www.mydomain.com')
NOTE: whenever possible, use the original url_for
because it has less overhead, and only use safe_url_for_external
in cases where context is not available.