【问题标题】:Django form validation error with incomplete fields but complete instance字段不完整但实例完整的 Django 表单验证错误
【发布时间】:2011-12-02 08:49:06
【问题描述】:

我希望能够做到:

def update_profile(request, username):
    user = Profile.objects.get(user__username=username)

    # update subset of profile, eg value_to_company is set in request.POST
    # but user (or an arbitrary number of other attributes) is not
    profile = ProfileForm(request.POST, instance=user)

    if not profile.is_valid():
        print profile.errors  #user is required

我遇到的问题是用户确实存在并且是实例的一部分,我在文档中找不到任何内容表明实例数据不会进入绑定数据。但我也找不到任何明确表示它的东西。

(剩下的就是我为什么要以我的方式做事的理由,以及解决方案的想法,你可能不需要阅读它。)

如果你想知道我为什么要填写表格——这对问题来说并不重要——那是因为我有这样的东西:

class Profile(models.Model):
    user = models.ForeignKey(auth.models.User)
    value_to_company = models.IntegerField()

class ValueField(forms.Field):
    def to_python(self, value):
        vals = {'high': 0,
                'mid': 1}
        return vals[value]

class ProfileForm(forms.ModelForm):
    value_to_company = ValueField()

    class Meta:
        model = Profile

也就是说,我已经在我的表单中执行 type api-to-internal-representation-coercion 并且我想继续使用它。

我可以重新实现 forms.is_valid() 循环,只检查表单上已经存在的字段,有点像 hacky:

# replaces `if not profile.is_valid()` above:
errors = []
for field in request.POST.iterkeys():
    if field in profile.fields:
        profile.fields[field].to_python()
        if not profile.fields['field'].clean():
            errors.append #something

(我没有真正看过逻辑内部逻辑,所以我知道这是错误的,但你明白了。)

【问题讨论】:

    标签: django validation django-forms modelform


    【解决方案1】:

    您可能只需要在表单中添加exclude = ('user',)。表单实例主要确定初始值,如果您的表单包含用户字段,但该字段以空白值发布,它尝试空白用户字段,从而导致错误。

    【讨论】:

    • 起初我认为这可行,但问题是它似乎重置了POST中未包含的所有字段。我只想更新模型,更改包含的内容。
    • user 应该以一种或另一种方式排除。您不希望用户将他们的个人资料与其他用户相关联。但是,通常,您必须为模型中未排除的每个字段提供一个实际的 HTML 字段。使用一个实例,它们都将预先填充当前设置的值。如果 HTML 表单中没有字段,或者用户明确将值设置为空,那么它将取消设置该字段。
    • 你说的对用户是正确的,我主要是想用一个常见的例子来证明我的模型有一个外键。但我猜你的意思是没有干净的方法来使用表单更新模型,除非你包含所有内容?在这种情况下,我实际上并没有显示任何表单,我正在尝试在我的 api 中重新使用它们的验证,并且我想让人们只使用他们想要更改的字段进行更新。
    • 不完全。您只需要将表格限制为您需要的内容。如果某些字段永远不会以这种方式更新,请将它们添加到exclude。但是,是的,您必须发布所有未排除字段的所有信息,即使该信息未更改。
    • 我也跳了。我也在使用表单来验证 RESTful API 并且遇到了同样的问题。我想支持字段更新。无论如何都不应取消设置那些必填字段。
    【解决方案2】:

    我在django-piston 中找到了this solution

    它在调用is_valid 之前添加了额外的表单方法merge_from_initial,它会填充给定对象中缺少的字段。

    我稍微改了一下,正在使用:

    class BaseModelForm(forms.ModelForm):
        """
        Subclass of `forms.ModelForm` which makes sure that the instance values are present in the form
        data, so you don't have to send all old values for the form to actually validate. Django does not
        do this on its own.
        """
    
        def merge_from_instance(self):
            # Internals
            self.data._mutable = True
    
            fun = lambda v: v not in self.data.keys()
            for field in filter(fun, self.fields.keys()):
                if field not in self.initial:
                    continue
                value = self.initial.get(field)
                if isinstance(self.instance._meta.get_field(field), related.ManyToManyField):
                    self.data.setlist(field, value)
                else:
                    self.data[field] = value
    

    【讨论】:

      猜你喜欢
      • 2012-09-10
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 2018-09-30
      • 2013-03-18
      • 1970-01-01
      • 2016-09-07
      • 1970-01-01
      相关资源
      最近更新 更多