Flask url_for

Jan 16, 2018

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.

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.