20

从源代码中,您可以看到 Django 1.4 的Form类有一个has_changed()方法和changed_data属性,看起来相当有用,但没有记录。我的问题是:按预期进行这些工作,即:

  • Form.clean(),如果任何表单数据发生变化则Form.has_changed()返回,否则TrueFalse
  • Form.clean(),Form.changed_data中是值已更改的字段名称列表。

如果是这样,除了关于使用未记录功能的常见警告/危险(即可能会更改、不受支持等)之外,是否有任何不使用它们的具体原因?

注意 1:要使这些与自定义小部件一起使用,这些小部件需要有一个_has_changed()方法,该方法是为内置小部件定义的。

注 2:有趣的是,文档确实包含了对该方法的临时提及Formset.has_changed(),但没有提及Form.has_changed().

4

3 回答 3

24

在进一步研究了 Django 源代码之后,借助 Florian 的回答中的有用提示,我可以报告这一点has_changedchanged_data按照我的问题中描述的方式进行工作,只要表单有办法获取初始数据来比较新数据。

那么问题来了,从 POST 数据创建的表单如何知道 GET 表单的初始值是什么?简短的回答是它没有——除非你以某种方式告诉它。有两种方法可以告诉它:

  1. 通过initial表单的关键字参数和/或initial字段的关键字参数,与您告诉 GET 表单初始值的方式完全相同。注意:如果你这样做,你需要确保你的 GET 和 POST 表单使用相同的值。这是唯一真正可靠的方法,因为您可以直接控制初始值。

  2. 您让 Django 通过为每个适用字段设置show_hidden_initial关键字参数来完成从 GET 中记住初始值的工作。True对于这些字段,Django 将具有初始值的隐藏输入元素呈现到 GET 表单的 HTML 中。稍后,当您调用POST 表单时has_changedchanged_data对于任何带有show_hidden_initialas的字段, TrueDjango 将自动从 POST 数据中的隐藏输入元素中获取初始值(取代来自initial表单或字段参数的任何初始值)。注意:与任何依赖 POST 数据的方法一样,这种方法最终是不可靠的,因为隐藏输入的值尽管被隐藏,但仍然可以更改。

于 2012-08-14T14:12:53.820 回答
7

您可以在两个条件下依赖这些方法:

  1. 您也可以在发布请求期间将初始数据字典传递给表单构造函数。
  2. 您不使用带有show_hidden_initial=True. (这些字段的问题是用户也可以提交用于比较的初始值,因此它不可信。)
于 2012-08-05T15:09:26.120 回答
1

这是一段代码,可以满足@Ghopper21 的建议。为了获取初始数据,我使用 QueryDict 上的 values() 函数。它返回一个包含属于该对象的数据的字典。一个重要的警告是我没有检查它如何处理外键引用。

saveStudentView(request,studentID):
    existingData = Student.objects.filter(id=paperID).values()[0]
    form = StudentForm(request.POST)
    if form.is_valid():
        form = StudentForm(request.POST, initial=existingData)
        if not form.has_changed():
            //Tell the user nothing has changed
        else:
            //Do other stuff
于 2017-05-31T07:03:13.540 回答