簡體   English   中英

Django 模板:創建一個“返回”鏈接?

[英]Django templates: create a "back" link?

我正在使用Django工具,我想知道是否有一種簡單的方法可以使用模板系統創建到上一頁的“返回”鏈接。

我認為在最壞的情況下,我可以從視圖函數中的請求對象中獲取此信息,並將其傳遞給模板渲染方法,但我希望我可以以某種方式避免所有這些樣板代碼。

我檢查了 Django 模板文檔,但沒有看到任何明確提到這一點的內容。

實際上是go(-1)

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

這個解決方案對我有用:

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

但這是之前在項目設置中向TEMPLATE_CONTEXT_PROCESSORS添加'django.core.context_processors.request',

那么你可以啟用:

'django.core.context_processors.request',

在您的settings.TEMPLATE_CONTEXT_PROCESSORS阻止並勾出引薦來源網址,但這有點令人作嘔,並且可能會到處崩潰。

大多數你想要這個的地方(例如 SO 上的編輯帖子頁面)都有一個真實的對象可以連接(在那個例子中,帖子),所以你可以輕松地計算出正確的前一頁應該是什么。

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

這里|escape用於擺脫" "字符串。

對於 RESTful 鏈接,“返回”通常意味着上一級:

<a href="../"><input type="button" value="Back" class="btn btn-primary" /></a>

您始終可以使用非常簡單的客戶端選項:

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

對於 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)

使用客戶端解決方案將是正確的解決方案。

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

此處提到的所有 Javascript 解決方案以及request.META.HTTP_REFERER解決方案有時都可以工作,但兩者都在同一場景中(也可能是其他場景)。

我通常在創建或更改對象的表單下有一個取消按鈕。 如果用戶提交一次表單並且服務器端驗證失敗,則會再次向用戶顯示包含錯誤數據的表單。 猜猜看, request.META.HTTP_REFERER現在指向顯示表單的 URL。 您可以按 Cancel 一千次,並且永遠不會回到最初的編輯/創建鏈接所在的位置。

我能想到的唯一可靠的解決方案有點復雜,但對我有用。 如果有人知道一個更簡單的解決方案,我很高興收到它。 :-) “技巧”是將初始 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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM