Django模板:创建一个“后退”链接?

时间:2009-02-08 02:02:04

标签: python django request referrer

我正在使用Django,我想知道是否有一种简单的方法可以使用模板系统创建到上一页的“后退”链接。

我认为在最坏的情况下,我可以从视图函数中的请求对象获取此信息,并将其传递给模板呈现方法,但我希望我能以某种方式避免所有这些样板代码。

我已经检查了Django模板文档,但我没有看到任何明确提到这一点的内容。

9 个答案:

答案 0 :(得分:30)

实际上是go(-1)

<input type=button value="Previous Page" onClick="javascript:history.go(-1);">

答案 1 :(得分:21)

这个解决方案适合我:

<a href="{{request.META.HTTP_REFERER}}">Go back</a>

但之前在项目设置中将'django.core.context_processors.request',添加到TEMPLATE_CONTEXT_PROCESSORS

答案 2 :(得分:12)

你可以启用:

'django.core.context_processors.request',

在你的settings.TEMPLATE_CONTEXT_PROCESSORS区块中并挂出引荐来源,但这有点令人作呕,可能会破坏所有地方。

大多数你想要的地方(例如SO上的编辑帖子页面)你有一个真实的对象可以挂钩(在那个例子中,帖子),这样你就可以很容易地找出正确的上一页应该是什么

答案 3 :(得分:1)

<a href="{{request.META.HTTP_REFERER|escape}}">Back</a>

|escape退出&#34;&#34; stringage

答案 4 :(得分:0)

您始终可以使用非常简单的客户端选项:

<a href="javascript:history.go(1)">Back</a>

答案 5 :(得分:0)

对于Django管理员更改表单中的“后退”按钮,我最终要做的是一个自定义模板过滤器,用于解析和解码模板中的“preserved_filters”变量。我将以下内容放在自定义的templates / admin / submit_line.html文件中:

<a href="../{% if original}../{% endif %}?{{ preserved_filters | decode_filter }}">
    {% trans "Back" %}
</a>

然后创建了自定义模板过滤器:

from urllib.parse import unquote
from django import template

def decode_filter(variable):
    if variable.startswith('_changelist_filters='):
        return unquote(variable[20:])
    return variable

register = template.Library()
register.filter('decode_filter', decode_filter)

答案 6 :(得分:0)

使用客户端解决方案将是正确的解决方案。

<a href="javascript:history.go(-1)" class="btn btn-default">Cancel</a>

答案 7 :(得分:0)

对于RESTful链接,其中“返回”通常意味着往上一级:

WebView(
        initialUrl: ur,
        javascriptMode: JavascriptMode.unrestricted,)

答案 8 :(得分:0)

此处提到的所有 Javascript 解决方案以及 request.META.HTTP_REFERER 解决方案有时都有效,但两者都在相同的情况下(也可能在其他情况下也有问题)。

我通常在创建或更改对象的表单下有一个取消按钮。如果用户提交一次表单并且服务器端验证失败,则会再次向用户显示包含错误数据的表单。猜猜看,request.META.HTTP_REFERER 现在指向显示表单的 URL。您可以按一千次取消,并且永远不会回到最初的编辑/创建链接所在的位置。

我能想到的唯一可靠的解决方案有点复杂,但对我有用。如果有人知道一个更简单的解决方案,我很高兴收到它。 :-) “技巧”是将初始 HTTP_REFERER 传递到表单中并从那里使用它。因此,当表单被 POST 到时,它会传递正确的初始引用。

我是这样做的:

我为完成大部分工作的表单创建了一个 mixin 类:

from django import forms
from django.utils.http import url_has_allowed_host_and_scheme

class FormCancelLinkMixin(forms.Form):
    """ Mixin class that provides a proper Cancel button link. """
    cancel_link = forms.fields.CharField(widget=forms.HiddenInput())

    def __init__(self, *args, **kwargs):
        """
        Override to pop 'request' from kwargs.
        """
        self.request = kwargs.pop("request")
        initial = kwargs.pop("initial", {})
        # set initial value of 'cancel_link' to the referer
        initial["cancel_link"] = self.request.META.get("HTTP_REFERER", "")
        kwargs["initial"] = initial
        super().__init__(*args, **kwargs)

    def get_cancel_link(self):
        """
        Return correct URL for cancelling the form.

        If the form has been submitted, the HTTP_REFERER in request.meta points to
        the view that handles the form, not the view the user initially came from.
        In this case, we use the value of the 'cancel_link' field.

        Returns:
            A safe URL to go back to, should the user cancel the form.

        """
        if self.is_bound:
            url = self.cleaned_data["cancel_link"]
            # prevent open redirects
            if url_has_allowed_host_and_scheme(url, self.request.get_host()):
                return url

        # fallback to current referer, then root URL
        return self.request.META.get("HTTP_REFERER", "/")

用于编辑/创建对象的表单(通常是 ModelForm 子类)可能如下所示:

class SomeModelForm(FormCancelLinkMixin, forms.ModelForm):
    """ Form for creating some model instance. """

    class Meta:
        model = ModelClass
    # ...

视图必须将当前请求传递给表单。对于基于类的视图,您可以覆盖 get_form_kwargs():

class SomeModelCreateView(CreateView):
    model = SomeModelClass
    form_class = SomeModelForm

    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs["request"] = self.request
        return kwargs

在显示表单的模板中:

<form method="post">
  {% csrf token %}
  {{ form }}
  <input type="submit" value="Save">
  <a href="{{ form.get_cancel_link }}">Cancel</a>
</form>