11

好的,我一直盯着这个几个小时试图弄清楚发生了什么,但无济于事。我正在尝试使用“instance”关键字创建一个 ModelForm 以将其传递给现有模型实例,然后保存它。这是 ModelForm(在我试图找出这个问题的原因时,从原来的版本中删除了很多):

class TempRuleFieldForm(ModelForm):
    class Meta:
        model = RuleField

这是我正在运行的代码:

>>> m = RuleField.objects.get(pk=1)
>>> f = TempRuleFieldForm(instance=m)
>>> f.is_valid()
False

模型对象(m上面)是有效的,它保存得很好,但表单不会验证。现在,据我所知,此代码与此处的 Django 文档示例相同:http: //docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method,但显然我错过了一些东西。我将非常感谢一些新鲜的眼睛来告诉我我做错了什么。

谢谢

4

4 回答 4

22

请注意,您的链接不会调用f.is_valid(),它只是直接保存。这可能有点误导。

关键是仅使用instance参数而不是 no实例化表单不会data将其绑定到数据,因此该表单无效。你会看到那是假的。f.is_bound

在幕后,instance实际上与传递initial数据相同,正如文档说明的那样,最初仅用于显示数据,不用于保存。您可能会从阅读有关绑定和未绑定表单的说明中受益。

于 2010-10-06T08:36:01.447 回答
3

如果你仍然想验证数据库中的对象,你可以先序列化它,然后用它创建表单。

from django.utils import simplejson
from django.core.serializers import serialize

(...)

fields_dict = simplejson.loads(serialize('json', [obj]))[0]['fields']
form = forms.MyForm(fields_dict)
if form.is_valid

这可能不是最好的方法,而是我发现的唯一一种从模型中获得绑定形式的方法。我需要它,因为我想验证数据库中的当前数据。我提出了一个问题,因为我认为这不是最好的方法:

将未绑定的表单转换为绑定的表单?

于 2012-01-24T20:38:07.700 回答
0

这不是 OP 的解决方案,但它是针对帖子标题的,这在 Google 中是相当高的。所以无论如何我都会从这里发布:

如果您已经使用 将 request.POST 提供给您的表单request.POST or None,但它仍然无效且没有错误,请检查是否存在任何重定向。重定向会丢失您的 POST 数据,并且您的表单将无效且没有错误,因为它未绑定。

于 2016-01-07T09:40:46.937 回答
0

对于 OP 来说不是一个解决方案,但这是我遇到的一个问题,特别是在 ModelForms 上运行单元测试时,继续绑定表单然后还定义一个具有相同数据的实例是一件令人讨厌的事情。我创建了一个小的辅助函数来简化其他人可能会觉得有用的事情——我只是将它用于测试目的,并且会谨慎地将其部署到其他任何地方而无需进行重大调整(如果有的话)

def testing_model_form(instance, model_form_class):
"""
A function that creates instances ModelForms useful for testing, basically takes an instance as an argument and will take care
of automatic binding of the form so it can be validated and errors checked
"""
fields = model_form_class.Meta.fields

data_dict = {}
for field in fields:
    if hasattr(instance, field):
        # The field is present on the model instance
        data_dict[field] = getattr(instance, field)
x = model_form_class(data=data_dict)
x.instance = instance
return x
于 2020-03-03T18:38:54.360 回答