【问题标题】:Django HttpResponseRedirect versus redirectDjango HttpResponseRedirect 与重定向
【发布时间】:2020-11-15 01:12:55
【问题描述】:

鉴于以下情况:

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')

【问题讨论】:

  • 两者是等价的。 redirectshortcuts 模块中定义以使其更短。它还有一个更方便的参数界面。
  • return redirect('tasks:index') 为什么我们在任务和索引之间使用冒号?

标签: django redirect httpresponse


【解决方案1】:

redirect(…)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))

其中resolve_urlreverse(…) function [Django-doc] 周围的一层,正如我们在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],它将返回此方法的结果;
  2. 如果是Promise,它将评估承诺;
  3. 如果是相对URL,则返回该URL;和
  4. 如果reverse(…) 失败并且它看起来像一个 URL,它将返回您自己传递的值,因为它假定它是一个(绝对)URL。

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

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

app_name = 'tasks'

urlpatterns = [
    # …,
    path('page/<slug:myslug>/', 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>)

【讨论】:

  • return redirect('tasks:index') 为什么我们在任务和索引之间使用冒号?
  • @TariqAhmed:tasks 是命名空间,如果您使用命名空间,则使用 namespace:viewname 指定视图名称。
  • 我没看懂..应该是&lt;slug:any_name&gt;我第一次看到这个namespace:viewname..
  • @TariqAhmed:这是一个 URL 参数:这里我们做相反的事情:我们从一个视图名称计算一个 URL。如果使用命名空间 URL(例如,如果 urs.py 包含 app_name),则必须添加前缀:docs.djangoproject.com/en/3.2/topics/http/urls/#introduction
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2016-09-27
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 2021-01-28
    • 2011-08-06
    • 2012-10-29
    • 2021-02-24
    • 2011-08-14
    相关资源
    最近更新 更多