Named URLs And The Reverse Function In Django

Named URLs And The Reverse Function In Django

Hard coding URLs, links, and redirects will get you a working application at the time you create it. It will also get you an application that will break as time goes on. On the web, URL structures sometimes change, and you need a way to make your application more flexible for these types of situations. Django offers Named URLs via the name= variable and the reverse resolution of URLs in your application code using the reverse() function. In this tutorial, we’ll test these features out in Django.


name= in urls.py

To get started using named URLs, we have to assign a name to one.

from django.urls import path
from . import views

urlpatterns = [
    path('<int:timeframe>', views.goals_by_int_timeframe),
    path('<str:timeframe>', views.goals_by_timeframe, name='namedurl'),
]

Notice the addition of the third argument in the second path() function. We have the keyword argument of name set to the string value of namedurl. Django is now able to identify this route directly by the string value ‘namedurl’.


reverse() function in views.py

The other side of this equation is to make use of the reverse() function in the views.py file. The reverse function needs to be imported first from django.urls before using it. The highlighted code below shows both the import and the usage.

from django.shortcuts import redirect, render
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse

# dictionary data store
goals = {
    'daily': 'Learn Something New',
    'weekly': 'Take a day off',
    'monthly': 'Complete a creative course'
}


def goals_by_int_timeframe(request, timeframe):
    timeframes = list(goals.keys())
    redirect_to = timeframes[timeframe - 1]
    named_redirect = reverse('namedurl', args=[redirect_to])
    return HttpResponseRedirect(named_redirect)


def goals_by_timeframe(request, timeframe):
    goal = goals[timeframe]
    return HttpResponse(goal)

Since the namedurl route has a variable (the captured <timeframe> variable), then this must be specified when calling the reverse() function. The way this is done is by specifying the keyword argument of args=. This argument expects a list so if you have only one value to pass in, just pass it as one value contained in a list. That is how we did it in the code here. Go ahead and test out the app by visiting http://127.0.0.1:8000/goals/1, http://127.0.0.1:8000/goals/2, and http://127.0.0.1:8000/goals/3. These URLs continue to work perfectly, even though we did not directly specify them in the redirect. The real benefit however is that the URL structure is much more robust to changes. Right now we get into this app from the main project urls.py via the ‘goals/’ route. What if that needed to change in the future? If the redirect above was hardcoded, it would be impossible and would cause the app to break. In our case, we *can* change that entry URL now thanks to Named URLs and the reverse() function. In the main project urls.py, let’s change ‘goals/’ to ‘tasks/’ and see what happens.

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('tasks/', include('goals.urls'))
]

The application continues to work, even with the new URL structure.

django named urls
django reverse function
django reverse with args


url Tag In HTML Templates

The reverse function is not used in templates to generate dynamic links. Instead, you would make use of the url tag to output links without having to hard-code URLs in your templates.

Named URLs And The Reverse Function In Django Summary

Whenever you need to create paths and links in a Django project, it is a good idea to avoid hard coding them and instead make use of Named URLs and the included reverse() function. If you hard code links and redirects, unforeseen URL changes may break your app entirely at a later time.