[英]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.