URL Building & Redirects with url_for
url_for is a Flask function that builds the correct URL for a view by its name, so you never hardcode a path again.
Learn URL Building & Redirects with url_for in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a…
Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll generate links from view names, attach query parameters, reference static files, and send the browser elsewhere with redirect .
url_for("view_name") asks Flask for the URL registered to a view function and returns it as a string. You pass the function's name (its endpoint ), and any route parameters as keyword arguments.
Because url_for needs to know about the request, we run it inside test_request_context() — a helper that fakes a request so the example works with no server running. In a real view, the context already exists.
Any keyword you pass that is not a route parameter becomes a query-string value. So url_for("search", q="flask", page=2) appends ?q=flask&page=2 automatically.
The built-in static endpoint generates URLs for your assets: url_for("static", filename="style.css") returns /static/style.css . If you hardcoded /static/... and later moved the folder or added a CDN prefix, every link would break — url_for stays correct.
In a Jinja template you'd write the same call: . That keeps your HTML links in sync with your routes.
redirect(target) tells the browser to go to another URL by sending a 302 response with a Location header. The idiomatic pattern is redirect(url_for("some_view")) so the destination is built from a name, not a hardcoded path.
This is the backbone of the Post/Redirect/Get pattern: after handling a form POST, you redirect to a result page so a browser refresh doesn't resubmit the form.
The status code 302 plus the Location: /user/ada header is exactly what a real browser receives — then it automatically requests that new URL.
Complete the code so it builds a profile URL, a search URL with a query, and a redirect. Replace each ___ .
❌ BuildError: Could not build url for endpoint
The endpoint name is wrong, or you forgot a required route parameter. Pass the exact view function name and every it declares, e.g. url_for("profile", username="ada") .
Calling url_for at import time fails because there's no request. Call it inside a view, a template, or a test_request_context() / app_context() block.
Build a route that redirects a short code to a full article URL.
Lesson complete — your links will never go stale!
You can build URLs from view names, attach query parameters, reference static files, and redirect cleanly with redirect(url_for(...)) .
🚀 Up next: Working with Cookies — store small pieces of data in the browser between requests.
Practice quiz
What does url_for build a URL from?
- A hardcoded path string
- The current request URL
- A regex pattern
- A view's endpoint name
Answer: A view's endpoint name. url_for('profile') looks up the route registered for that view's endpoint and returns its path.
What does url_for('profile', username='ada') produce for /user/<username>?
- /profile?username=ada
- /user/ada
- /user/<username>
- /ada
Answer: /user/ada. The keyword matches the route parameter, filling the dynamic segment to give /user/ada.
How does url_for handle a keyword that is NOT a route parameter?
- It appends it as a query string
- It raises an error
- It ignores it
- It adds it to the path
Answer: It appends it as a query string. Extra keywords become a query string, so url_for('search', q='flask', page=2) gives /search?q=flask&page=2.
Which endpoint name links static files?
- files
- assets
- static
- public
Answer: static. url_for('static', filename='css/style.css') uses the built-in 'static' endpoint to return /static/css/style.css.
Which idiomatic call redirects to a named view?
- go(url_for('home'))
- redirect('/home')
- send(url_for('home'))
- redirect(url_for('home'))
Answer: redirect(url_for('home')). redirect(url_for('view')) builds the destination from a name rather than a hardcoded path.
What HTTP status code does redirect() send by default?
- 200
- 302
- 404
- 500
Answer: 302. redirect() returns a 302 response with a Location header pointing at the target URL.
Why avoid hardcoding URLs like '/user/ada'?
- They break when you rename a route or add a prefix
- They load more slowly
- They are not valid HTML
- They disable caching
Answer: They break when you rename a route or add a prefix. Hardcoded strings break when the URL map changes; url_for asks Flask for the current path.
Why must url_for run inside a request or test_request_context()?
- To compress the URL
- Because it needs an active request context
- To enable CSRF
- To cache the result
Answer: Because it needs an active request context. Calling url_for at import time fails; it needs a view, a template, or a test_request_context() block.
Which header carries the destination of a 302 redirect?
- Refresh
- Redirect
- Location
- Forward
Answer: Location. A redirect sets the Location header, which the browser then follows to the new URL.
What raises a BuildError from url_for?
- Passing too many query params
- Using it inside a template
- Calling redirect first
- A wrong endpoint name or a missing route parameter
Answer: A wrong endpoint name or a missing route parameter. BuildError means the endpoint name is wrong or a required <param> was not supplied.