When I read django code sometimes, I see in some templates reverse()
. I am not quite sure what this is but it is used together with HttpResponseRedirect. How an
The reverse() is used to adhere the django DRY principle i.e if you change the url in future then you can reference that url using reverse(urlname).
This is an old question, but here is something that might help someone.
From the official docs:
Django provides tools for performing URL reversing that match the different layers where URLs are needed: In templates: Using the url template tag. In Python code: Using the reverse() function. In higher level code related to handling of URLs of Django model instances: The get_absolute_url() method.
Eg. in templates (url tag)
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
Eg. in python code (using the reverse
function)
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
The existing answers are quite clear. Just in case you do not know why it is called reverse
: It takes an input of a url name and gives the actual url, which is reverse to having a url first and then give it a name.
The function supports the dry principle - ensuring that you don't hard code urls throughout your app. A url should be defined in one place, and only one place - your url conf. After that you're really just referencing that info.
Use reverse()
to give you the url of a page, given either the path to the view, or the page_name parameter from your url conf. You would use it in cases where it doesn't make sense to do it in the template with {% url 'my-page' %}
.
There are lots of possible places you might use this functionality. One place I've found I use it is when redirecting users in a view (often after the successful processing of a form)-
return HttpResponseRedirect(reverse('thanks-we-got-your-form-page'))
You might also use it when writing template tags.
Another time I used reverse()
was with model inheritance. I had a ListView on a parent model, but wanted to get from any one of those parent objects to the DetailView of it's associated child object. I attached a get__child_url()
function to the parent which identified the existence of a child and returned the url of it's DetailView using reverse()
.
There is a doc for that
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse-resolution-of-urls
it can be used to generate an URL for a given view
main advantage is that you do not hard code routes in your code.
Existing answers did a great job at explaining the what of this reverse()
function in Django.
However, I'd hoped that my answer shed a different light at the why: why use reverse()
in place of other more straightforward, arguably more pythonic approaches in template-view binding, and what are some legitimate reasons for the popularity of this "redirect via reverse()
pattern" in Django routing logic.
One key benefit is the reverse construction of a url, as others have mentioned. Just like how you would use {% url "profile" profile.id %}
to generate the url from your app's url configuration file: e.g. path('<int:profile.id>/profile', views.profile, name="profile")
.
But as the OP have noted, the use of reverse()
is also commonly combined with the use of HttpResponseRedirect
. But why?
I am not quite sure what this is but it is used together with HttpResponseRedirect. How and when is this reverse() supposed to be used?
Consider the following views.py
:
from django.http import HttpResponseRedirect
from django.urls import reverse
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected = question.choice_set.get(pk=request.POST['choice'])
except KeyError:
# handle exception
pass
else:
selected.votes += 1
selected.save()
return HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
))
And our minimal urls.py
:
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('<int:question_id>/results/', views.results, name='polls-results'),
path('<int:question_id>/vote/', views.vote, name='polls-vote')
]
In the vote()
function, the code in our else
block uses reverse
along with HttpResponseRedirect
in the following pattern:
HttpResponseRedirect(reverse('polls:polls-results',
args=(question.id)
This first and foremost, means we don't have to hardcode the URL (consistent with the DRY principle) but more crucially, reverse()
provides an elegant way to construct URL strings by handling values unpacked from the arguments (args=(question.id)
is handled by URLConfig). Supposed question
has an attribute id
which contains the value 5
, the URL constructed from the reverse()
would then be:
'/polls/5/results/'
In normal template-view binding code, we use HttpResponse()
or render()
as they typically involve less abstraction: one view function returning one template:
def index(request):
return render(request, 'polls/index.html')
But in many legitimate cases of redirection, we typically care about constructing the URL from a list of parameters. These include cases such as:
POST
requestMost of these involve some form of redirection, and a URL constructed through a set of parameters. Hope this adds to the already helpful thread of answers!