【问题标题】:Is it possible to dynamically change the attribute of a form widget at run time是否可以在运行时动态更改表单小部件的属性
【发布时间】:2016-09-28 18:32:43
【问题描述】:

我目前有一个看起来像这样的对象

class StudentDetails(forms.Form):
    school_name = forms.CharField(required=True, widget=forms.TextInput(attrs={'readonly': 'readonly'}))
    student_name= forms.CharField(required=True)
    student_user_name = forms.CharField(required=True)

现在这些字段在渲染之前被预先填充到视图中

 return render(request, 'manageStudent.html',
                  {'form': StudentDetails(
                      initial={
                          'school_name': rslt[0][1],
                          'student_name': rslt[0][2],
                          'student_user_name': rslt[0][3]
                      })})

我的问题是是否可以禁用 student_user_name 字段?我想将启用的字段表单切换为禁用?

【问题讨论】:

    标签: django forms widget


    【解决方案1】:

    首先,一般来说,在表单中使用禁用/只读字段不是一个好主意,特别是如果您真的不希望用户弄乱这些字段的值。

    最安全的选择是有条件地删除表单 init 中的表单字段,而是将数据从视图本身传递到模板中以便打印。

    如果您还想继续,请确保在您的视图 POST 处理中根本不依赖此表单字段。使用您在视图中已经知道的字段值应该是什么。

    另外请记住,禁用和只读表单字段之间存在重要区别。 Readonly 会将值传递给您的 POST 数据,而 disabled 则不会。为什么这有关系 ? (因为您无论如何都不会使用该值,正如我们所谈到的)。

    确实如此,原因有二:

    (1) 如果表单验证由于某种原因失败,您打算在禁用字段中显示的任何内容都将消失,因为 POST 的返回不会捕获该字段值。

    (2) 如果表单字段像您的情况一样是“必需的”,它会给您该字段的表单验证错误,因为该值不会保留在 POST 数据中。

    为避免这种情况,您可以尝试在隐藏的表单字段中捕获值并使用 javascript/jquery 将值放入字段中。下面是一个例子:

    def __init__(self, *args, **kwargs):
        super(StudentDetails, self).__init__(*args, **kwargs)
        if 'initial' in kwargs:
            _student_user_name = str(kwargs.get('initial').get('student_user_name', None))
            if _student_user_name: 
                self.fields['student_user_name'].widget.attrs['disabled'] = True
                self.fields['student_user_name'].required = False
                self.fields['hidden_student_user_name'] = forms.CharField(widget=forms.HiddenInput())
                self.fields['hidden_student_user_name'].initial = _student_user_name
    

    请记住,即使我们将 student_user_name 存储在隐藏表单字段中,隐藏表单字段也可能被篡改。因此,请勿将视图中的隐藏值用于任何实际存储,而仅用于重新填充已禁用表单字段值的失败提交表单显示,仅用于装饰目的。

    因此,即使禁用的表单字段值将消失(这就是我们将其保存在该隐藏表单字段中的原因),您可以确保在表单提交失败期间仍会显示您为学生用户名发送的初始值:

    在显示表单的模板页面中,将这段 javascript 代码放入:

    <script type="text/javascript">
    $(document).ready(function() {
          if ( $('input[name=hidden_student_user_name]').val() ) {
             var hidden_student_user_name = $('input[name=hidden_student_user_name]').val()
             $('input[name=student_user_name]').prop('disabled', false)
             $('input[name=student_user_name]').val(hidden_student_user_name)
             $('input[name=student_user_name]').prop('disabled', true)
          }
    });
    </script>
    

    【讨论】:

      【解决方案2】:

      您可以通过将字段的disabled 参数设置为True 来禁用它。

      更多信息在这里:https://docs.djangoproject.com/en/1.9/ref/forms/fields/#disabled

      或者,当您在网页上更改它时,您可以添加一个复选框来控制小部件的行为,如下所示:

      在模板中,您将拥有student_user_nameinput,因此您只需在表单中添加复选框按钮

      <!-- Input of the 'student_user_name' will be already there if you use {{ form }}-->
      <!-- <input type="text" name="student_user_name" />-->
      <input type="checkbox" id="checkbox"/>
      

      在 JavaScript 文件中

      $(document).ready(function() {
          $("#checkbox").change(function(){
              if (this.checked){
                  $("input[name=student_user_name]").attr("disabled", true);
              } else {
                  $("input[name=student_user_name]").attr("disabled", false);
              }
          });
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-29
        • 1970-01-01
        • 2019-01-21
        相关资源
        最近更新 更多