Django HttpResponseRedirect 与重定向

Django HttpResponseRedirect versus redirect

鉴于以下情况:

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()
    })

有什么区别,你为什么要用一个而不是另一个,介于:

return HttpResponseRedirect(reverse("tasks:index"))

和:

return redirect('tasks:index')

redirect(…) is implemented as [GitHub]:

def redirect(to, *args, permanent=False, **kwargs):
    redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    return <b>redirect_class(</b>resolve_url(to, *args, **kwargs)<b>)</b>

其中 resolve_urlreverse(…) 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

因此这是解决 URL 的更“丰富”的方法,因为:

  1. 如果对象有 .get_absolute_url() method [Django-doc] 它将 return 此方法的结果;
  2. 如果是Promise,它将评估承诺;
  3. 如果是亲戚URL,它将return URL;和
  4. 如果 reverse(…) 失败 并且它看起来像 URL,它将 return 您传递给自己的值,从那时起它假设它是一个(绝对)URL.

因此,它不仅旨在找到具有该名称的视图,而且还会做一些额外的事情。

此外,使用重定向的参数使用方式更方便。如果 url 看起来像:

app_name = 'tasks'

urlpatterns = [
    # …,
    path('page/<b><slug:myslug></b>/', some_view, name='page')
]

然后当您使用 reverse(…) 时,您为 myslug 参数提供一个值:

return HttpResponseRedirect(reverse('tasks:index'<b>, args=('value',)</b>))

或:

return HttpResponseRedirect(reverse('tasks:index'<b>, kwargs={'myslug': 'value'}</b>))

而对于重定向,您可以使用:

return redirect('tasks:index'<b>, 'value'</b>)

或:

return redirect('tasks:index'<b>, myslug='value'</b>)

就功能而言,就可读性而言,没有区别,是的!

HttpResponseRedirect 来自 django.http 库,redirect() 来自 django.shortcuts 库。

这与使用 render() [来自 django.shortcuts] 函数或 TemplateResponse() [来自 django.templates]

相同