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.