【问题标题】:Overriding initial value in ModelForm覆盖 ModelForm 中的初始值
【发布时间】:2011-02-28 15:13:23
【问题描述】:

在我的 Django (1.2) 项目中,我想在模型表单中预填充一个字段,但我的新值被忽略了。 这是sn-p:

class ArtefactForm(ModelForm):
    material = CharField(widget=AutoCompleteWidget('material', force_selection=False))

    def __init__(self, *args, **kwargs):
        super(ArtefactForm, self).__init__(*args, **kwargs)
        self.fields['material'].initial = 'Test'

我也尝试了self.base_fields,但没有效果:表单中始终显示数据库值。有什么想法吗?

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    试试这个:

    def __init__(self, *args, **kwargs):
        initial = kwargs.get('initial', {})
        initial['material'] = 'Test'
        kwargs['initial'] = initial
        super(ArtefactForm, self).__init__(*args, **kwargs)
    

    【讨论】:

      【解决方案2】:

      老问题,但添加了一个描述性的答案,因为我相信这对一些新开发人员会有所帮助。

      我也试过self.base_fields,但没有效果:表格中总是显示数据库值。有什么想法吗?

      如果表单是“初始化”表单,则:-

      1. 使用initial 参数(例如YourModelFrom(initial={'filed1': variable}) — 通常情况下,当您想为某些字段传递动态计算的初始值时)。参考Setting Initial Values

      2. 使用instance 参数(例如YourModelFrom(instance=model_object) — 通常情况下,当您想要更新现有模型实例对象时)。参考阅读 ModelFrom 的save() method

        注意:
        1 `ModelFrom` 类继承 `BaseModelFrom` 类。 `BaseModelFrom` 类继承 `BaseForm` 类。
        2 参数instance 被添加到`BaseModelFrom` 类构造函数中,当我们将模型类实例对象分配给instance 参数(因此instance is not None)然后`BaseModelFrom` 构造函数调用model_to_dict() 并更新initial 参数之前调用超类构造函数。检查 BaseModelFrom 类中的def __init__

      然后显式地为字段分配初始值(如相关的 OP 代码所示)不起作用,这是由于 _clean_fields 方法在 BaseFrom 类中的编写方式。

      代码片段:

      def _clean_fields(self):
          for name, field in self.fields.items():
              value = field.widget.value_from_datadict(
                      self.data, self.files, self.add_prefix(name))
              try:
                  if isinstance(field, FileField):
                      initial = self.initial.get(name, field.initial) # <- Check
                      value = field.clean(value, initial)
                  else:
      

      根据代码行initial = self.initial.get(name, field.initial),如果字段的初始值在initial dict 中给出,则分配给field.initial 的值使用。

      [回答]

      虽然,@Daniel 的答案是完全正确的,但人们也可以喜欢另一种达到相同效果的方法是使用self.initial

      def __init__(self, *args, **kwargs):
          super(ArtefactForm, self).__init__(*args, **kwargs)
          self.initial['material'] = 'Test'
      

      试试看!!

      self.initial 只不过是我们在参数中传递的字典。 BaseForm中的校验码__init__

      class BaseForm(object):
          def __init__(........
                       ........):
              :
              self.prefix = prefix
              self.initial = initial or {}  # <-- Notice 
              self.error_class = error_class
              :
      

      注意:我没有找到任何与使用初始属性相关的文档,我只是探索了基础代码并使用了它。

      编辑:问题中报告的行为也记录在 Django 模型中

      Dynamic initial values

      Form.initial

      请注意,如果 Field 定义了 initial 并且 包含 initial 时 实例化表单,则后者initial 将具有优先权。 在此示例中,initial 在字段级别和在 表单实例级别,后者优先:

      >>> from django import forms
      >>> class CommentForm(forms.Form):
      ...     name = forms.CharField(initial='class')
      ...     url = forms.URLField()
      ...     comment = forms.CharField()
      >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
      >>> print(f)
      <tr><th>Name:</th><td><input type="text" name="name" value="instance" />
      <tr><th>Url:</th><td><input type="url" name="url" /></td></tr>
      <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
      

      PS:顺便说一句,我的答案中的第 2 点说明了 initialinstance 参数之间的区别。它们是另一个键值参数data - 触发表单验证的值。阅读此Difference between Django Form 'initial' and 'bound data'?

      【讨论】:

      • 注意:在绑定形式中,data(查询字典)将优先于初始化字段的值。检查代码:def value(self) 和方法def bound_data(self, data, initial) - 如果您有动态计算的字段 os 的值并且该字段为 'disabled',这将对您有所帮助。如果有人需要帮助,请告诉我,我会更新这个答案!
      猜你喜欢
      • 1970-01-01
      • 2019-08-11
      • 2020-08-23
      • 2018-01-11
      • 1970-01-01
      • 1970-01-01
      • 2016-03-20
      • 1970-01-01
      • 2013-07-06
      相关资源
      最近更新 更多