Reputation: 15665
Given the following:
def add(request):
if request.method == "POST":
task = request.POST.get('task')
form = NewTaskForm(request.POST)
if form.is_valid():
task = form.cleaned_data["task"]
request.session['tasks'] += [task]
# return HttpResponseRedirect(reverse("tasks:index"))
return redirect('tasks:index')
else:
return render(request, "tasks/add.html",{
"form": form
})
return render(request, "tasks/add.html",{
"form": NewTaskForm()
})
what's the difference, why would you use one over the other, between:
return HttpResponseRedirect(reverse("tasks:index"))
and:
return redirect('tasks:index')
Upvotes: 2
Views: 2426
Reputation: 408
There's no difference, in terms of functionality, in terms of readability, yes!
HttpResponseRedirect comes from django.http library and redirect() comes from django.shortcuts library.
It's the same like using the either the render() [comes from django.shortcuts] function or TemplateResponse() [comes from django.templates]
Upvotes: 1
Reputation: 476659
redirect(…)
is implemented as [GitHub]:
def redirect(to, *args, permanent=False, **kwargs): redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect return redirect_class(resolve_url(to, *args, **kwargs))
where resolve_url
is a layer around the reverse(…)
function [Django-doc], as we can see in the source code [GitHub]:
def resolve_url(to, *args, **kwargs): """ Return a URL appropriate for the arguments passed. The arguments could be: * A model: the model's `get_absolute_url()` function will be called. * A view name, possibly with arguments: `urls.reverse()` will be used to reverse-resolve the name. * A URL, which will be returned as-is. """ # If it's a model, use get_absolute_url() if hasattr(to, 'get_absolute_url'): return to.get_absolute_url() if isinstance(to, Promise): # Expand the lazy instance, as it can cause issues when it is passed # further to some Python functions like urlparse. to = str(to) if isinstance(to, str): # Handle relative URLs if to.startswith(('./', '../')): return to # Next try a reverse URL resolution. try: return reverse(to, args=args, kwargs=kwargs) except NoReverseMatch: # If this is a callable, re-raise. if callable(to): raise # If this doesn't "feel" like a URL, re-raise. if '/' not in to and '.' not in to: raise # Finally, fall back and assume it's a URL return to
It is thus a more "rich" way to resolve URL's since:
.get_absolute_url()
method [Django-doc] it will return the result of this method;Promise
, it will evaluate the promise;reverse(…)
fails and it looks like a URL, it will return the value you passed itself, since then it assumes it is an (absolute) URL.It thus does not only aim to find a view with that name, but does some extra things.
Furthermore the way you use parameters is more convenient with redirect. If the url looks like:
app_name = 'tasks'
urlpatterns = [
# …,
path('page/<slug:myslug>/', some_view, name='page')
]
then when you use reverse(…)
, you provide a value for the myslug
parameter with:
return HttpResponseRedirect(reverse('tasks:index', args=('value',)))
or:
return HttpResponseRedirect(reverse('tasks:index', kwargs={'myslug': 'value'}))
whereas with a redirect, you can use:
return redirect('tasks:index', 'value')
or:
return redirect('tasks:index', myslug='value')
Upvotes: 3