【问题标题】:Rendering a value as text instead of field inside a Django Form将值呈现为文本而不是 Django 表单中的字段
【发布时间】:2010-11-11 04:04:01
【问题描述】:

有没有简单的方法让Django将{{myform.name}}渲染为

John Smith

而不是

<input id="id_name" name="name" value="John Smith" />

&lt;form&gt; 标签内?还是我走错了路?

【问题讨论】:

    标签: django django-templates django-forms


    【解决方案1】:

    这是上面@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 在他随后的评论中正确指出的那样,这种方法并不能有效防止用户更改在隐藏字段中发回的数据。 “所有用户输入都是邪恶的”。

    【讨论】:

      【解决方案2】:

      老话题了,不过我觉得还是有人来的。

      你也可以这样做:

      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]
      【解决方案3】:
      <form>
          {% for field in form %}
                  {{ field.label }}: {{ field.value }}
          {% endfor %}
      </form>
      

      看看这里Form fieldsWorking with forms

      【讨论】:

      • 谢谢 - 我看到了 .label 但没有看到 .initial。奇怪的是,“使用表单”文档中甚至没有提到 .initial。
      • .initial 仅在第一次显示表单时有效,对吗?例如,如果出现错误并且您重新提交表单,根据我的经验,不会有首字母。
      • 在 Django 术语中,这只适用于未绑定的表单。如果您希望它同时使用未绑定和绑定表单怎么办?
      【解决方案4】:

      我认为这就是你想要的: http://code.djangoproject.com/ticket/10427

      我修补了我的 django,瞧……

      【讨论】:

        【解决方案5】:

        为什么不使用 {{ field.data }} ?

        【讨论】:

        • 因为它应该在不在模板中的视图中完成(在模板中是循环)
        【解决方案6】:

        另外,别忘了你也可以{{myform.instance.name}}

        【讨论】:

        • 这是什么?它记录在哪里?
        • form.instance 返回绑定表单所代表的对象。它在此处的文档中:docs.djangoproject.com/en/dev/topics/forms/modelforms/… 我还应该提到这仅适用于模型表单
        • 啊,谷歌应用引擎不支持ModelForm,所以我们使用Form。
        【解决方案7】:

        您还可以使用新的小部件:我这样做是为了创建一个小部件,该小部件创建一个日期的文本显示,以及一个包含相同日期的隐藏表单,以便用户可以看到它,但他们无法改变它。

        这是一个初始(仍在测试/待清理)版本:

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

        【讨论】:

        • 这种方法对我来说非常有用,因为除了显示值的“普通”版本外,它还创建了一个副本,在表单发布时传递。我对其进行了调整以制作一个更通用的版本(请参阅我的答案进一步向下)
        • 请记住,恶意用户很容易更改此值。您可能想让表单字段返回它的初始值。
        • 我赞成。像这样的技术对于在表示层中保持状态非常有帮助,但是如果要在应用层使用,则必须彻底验证从用户表单或会话发回的任何数据项。
        猜你喜欢
        • 2020-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-07
        • 1970-01-01
        • 2011-09-06
        • 1970-01-01
        • 2021-11-16
        相关资源
        最近更新 更多