【问题标题】:How to determine if a field has changed in a Django modelform如何确定 Django 模型表单中的字段是否已更改
【发布时间】:2016-06-23 02:10:23
【问题描述】:

我很惊讶这很难做到。但是我想出了这个,这似乎至少适用于我的简单案例。谁能推荐一个更好的方法?

def field_changed(self, fieldname):
    """Tests if the value of the field changed from the original data"""
    orig_value = self.fields[fieldname].initial or getattr(self.instance, field, None)
    orig_value = getattr(orig_value, 'pk', orig_value)
    if type(orig_value) is bool:
        # because None and False can be interchangeable
        return bool(self.data.get(fieldname)) != bool(orig_value)
    else:
        return unicode(self.data.get(fieldname)) != unicode(orig_value)

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    Form 包含一个属性 changed_data,它包含所有值已更改的字段的列表。

    试试:

    'fieldname' in myforminstance.changed_data
    

    【讨论】:

    • 技术说明:如果表单字段使用模型字段默认值呈现,该默认值之前未设置(例如在创建时),那么除非更改默认值,否则该字段的名称将不会在changed_data 列表中
    【解决方案2】:

    看来你重新发明了.has_changed() 方法。

    【讨论】:

    • 如有疑问,请搜索文档;或者我还发现检查 django 代码是查找所有可用方法的好方法。
    • 是的,django 源代码有据可查,并且在某些方面很有教益。好的 IDE 也有助于直接从项目文件轻松访问源代码。
    • 拒绝投票为field.has_changed() 似乎需要 2 个必需的位置参数:“初始”和“数据”。这将需要检索原始表单数据和新表单数据,此时您不妨自己比较新旧条目。 Airs's answer 更直接。
    【解决方案3】:

    Airs's answer 上扩展,用于多个字段:

    在您想要跟踪字段列表的更改['field_a', 'field_b', 'field_c']的场景中


    如果您想检查这些字段中的任何是否已更改:

    any(x in myforminstance.changed_data for x in ['field_a', 'field_b', 'field_c'])
    

    如果您想检查所有这些字段是否已更改:

    all(x in myforminstance.changed_data for x in ['field_a', 'field_b', 'field_c'])
    

    【讨论】:

      【解决方案4】:

      您必须重写方法post_save。覆盖方法是 Django 中的一个好习惯:https://docs.djangoproject.com/en/dev/ref/signals/#post-save

      我建议你在你的模型类中添加这样的东西:

          def post_save(self, sender, instance, created, raw, using, update_fields):
              if 'the_field' in update_fields:
                 # Do whatever...
      

      【讨论】:

      • 信号的重点不是覆盖而是监听信号
      • update_fields 不列出已更改的字段,它仅列出在 save() 方法上传递给 update_fields 的字段。因此,一个字段可能会更改,而不会包含在 update_fields 中。
      • 您还可以使用post_save 中提供的任何参数来确定吗?
      • post_save 函数符号应包含 **kwargs,以便 (sender, update_fields, created, instance, **kwargs) 将用作 post_save 参数
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多