what is reverse() in Django

前端 未结 7 1577
Happy的楠姐
Happy的楠姐 2020-11-30 16:40

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

7条回答
  •  春和景丽
    2020-11-30 17:17

    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('/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('/results/', views.results, name='polls-results'),
        path('/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:

    • HTML form submission through POST request
    • User login post-validation
    • Reset password through JSON web tokens

    Most 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!

提交回复
热议问题