【发布时间】:2010-11-11 04:04:01
【问题描述】:
有没有简单的方法让Django将{{myform.name}}渲染为
John Smith
而不是
<input id="id_name" name="name" value="John Smith" />
在<form> 标签内?还是我走错了路?
【问题讨论】:
标签: django django-templates django-forms
有没有简单的方法让Django将{{myform.name}}渲染为
John Smith
而不是
<input id="id_name" name="name" value="John Smith" />
在<form> 标签内?还是我走错了路?
【问题讨论】:
标签: django django-templates django-forms
这是上面@Matthew_Schinkel 建议的方法,使用 Django 2.2 和 python 3。
from django.utils.safestring import mark_safe
class PlainTextWidgetWithHiddenCopy(forms.Widget):
def render(self, name, value, attrs, renderer=None):
if hasattr(self, 'initial'):
value = self.initial
return mark_safe(
(str(value) if value is not None else '-') +
f"<input type='hidden' name='{name}' value='{value}'>"
)
这是一个自定义小部件,它将字段的内容呈现为纯文本,后跟一个 html 标记,该标记创建一个与原始字段具有相同名称和值的隐藏字段。
这意味着除了向用户显示的值之外,它还由浏览器保存并继续发送到处理提交表单的视图。
如果表单 POST 到自身,这将特别方便,否则纯文本数据会因为字段的 initial 值尚未设置而消失。
例如,如果您的表单包含:
my_field = forms.IntegerField(
widget=PlainTextWidgetWithHiddenCopy,
initial=12345)
那么该字段将呈现为以下html:
12345<input type='hidden' name='my_field' value='12345'>
当表单提交时,相应视图接收到的POST数据会包括:
{'my_field': '12345'}
这意味着如果视图现在重新呈现表单,那么 my_field 的值将再次设置为 12345,就像请求是 GET 一样。
正如 Matthew 在他随后的评论中正确指出的那样,这种方法并不能有效防止用户更改在隐藏字段中发回的数据。 “所有用户输入都是邪恶的”。
【讨论】:
老话题了,不过我觉得还是有人来的。
你也可以这样做:
from django.utils.safestring import mark_safe
class PlainTextWidget(forms.Widget):
def render(self, _name, value, _attrs):
return mark_safe(value) if value is not None else '-'
在你的表单中
class SomeForm(Form):
somename = forms.CharField(widget=PlainTextWidget)
在 Django 2.1+ 下,您需要以下内容:
from django.utils.safestring import mark_safe
class PlainTextWidget(forms.Widget):
def render(self, name, value, attrs=None, renderer=None):
return mark_safe(value) if value is not None else '-'
【讨论】:
def render(self, name, value, attrs): 在 django 1.10 中(?不确定它是否在其他版本中,或者为什么我的版本不需要下划线?)所以没有 [_name 和 _attrs]
<form>
{% for field in form %}
{{ field.label }}: {{ field.value }}
{% endfor %}
</form>
【讨论】:
我认为这就是你想要的: http://code.djangoproject.com/ticket/10427
我修补了我的 django,瞧……
【讨论】:
为什么不使用 {{ field.data }} ?
【讨论】:
另外,别忘了你也可以{{myform.instance.name}}
【讨论】:
您还可以使用新的小部件:我这样做是为了创建一个小部件,该小部件创建一个日期的文本显示,以及一个包含相同日期的隐藏表单,以便用户可以看到它,但他们无法改变它。
这是一个初始(仍在测试/待清理)版本:
class DayLabelWidget(forms.Widget):
def render(self, name, value, attrs):
final_attrs = self.build_attrs(attrs, name=name)
if hasattr(self, 'initial'):
value = self.initial
if type(value) == type(u''):
value = datetime.date(*map(int, value.split('-')))
return mark_safe(
"%s" % value.strftime("%A (%d %b %Y)")
) + mark_safe(
"<input type='hidden' name='%s' value='%s' />" % (
name, value
)
)
def _has_changed(self, initial, data):
return False
然后在字段中将其用作(widget=DayLabelWidget,)。
【讨论】: