【问题标题】:django alter form data in clean methoddjango 在 clean 方法中更改表单数据
【发布时间】:2011-07-13 15:02:15
【问题描述】:

我有一个想要自定义清理的 django 表单。我不想只指定像这里 (Django form and field validation) 这样的错误消息,而是自己更改该字段。我尝试了多种方法,但不断遇到错误,例如cleaned_data 是不可变的。

为了解决这个问题,我制作了一个副本,对其进行了更改并将其重新分配给自己。这是最好的方法吗?我可以/应该在视图中处理这个吗?制作副本似乎很糟糕,但我一直遇到“不可变”的障碍。下面的示例代码我只是检查主题末尾是否有“--help”,如果没有则添加它。谢谢

def clean(self):
        cleaned_data=self.cleaned_data.copy()
        subject=cleaned_data.get['subject']
        if not subject.endswith('--help'):
            cleaned_data['subject']=subject+='--help'
        self.cleaned_data=cleaned_data
        return self.cleaned_data

【问题讨论】:

标签: django forms


【解决方案1】:

处理此问题的正确方法是使用特定于字段的清理方法。

无论您从clean_FOO 方法返回什么,当它到达clean 函数时,cleaned_data 将被填充。

改为执行以下操作:

def clean_subject(self):
        data = self.cleaned_data.get('subject', '')
        if not data:
             raise forms.ValidationError("You must enter a subject")
             # if you don't want this functionality, just remove it.

        if not data.endswith('--help'):
             return data += '--help'
        return data

【讨论】:

  • 这真的很有帮助,因为文档在这一点上不清楚。
  • 这是正确的,但只有在涉及一个字段时才能这样做。如果需要另一个值,则必须使用 clean
【解决方案2】:

我认为您的问题是您调用了self.cleaned_data.get['subject'],然后将其用作数组。

我有一个消息应用程序的代码,它用“无主题”替换空主题

def clean(self):
    super(forms.ModelForm, self).clean()
    subject = self.cleaned_data['subject']
    if subject.isspace():
        self.cleaned_data['subject'] = 'No Subject'
    return self.cleaned_data

对于您的代码,这应该可以工作。

def clean(self):
    super(forms.Form, self).clean() #I would always do this for forms.
    subject = self.cleaned_data['subject']
    if not subject.endswith('--help'):
        subject += '--help'
        self.cleaned_data['subject'] = subject
    return self.cleaned_data

【讨论】:

  • 好的,太好了!我在 clean 方法中更改它,但是当它返回视图时。该字段未更改。也许这一直是问题?你能看看我是如何设置视图的吗?
  • view is:def createNote(request): if (request.method == 'POST'): e = noteForm(request.POST) try: e.is_valid() newE=e.save( commit=False) newE.save() redirect='/notes/' return HttpResponseRedirect(redirect) except Exception, error: print "Failed in register", error else: e = noteForm() return render_to_response('event_form.html', {'e': e,})
【解决方案3】:

所以,我最近发现这可能是相同的问题,在表单的 ModelForm 实例中,我试图在验证后编辑数据,以便为最终用户提供关于可能会出现的问题的建议一个有效的响应(根据他们在表单中输入的另一个值计算)。

TL;DR

如果您要专门处理 ModelForm 后代,有两件事很重要:

  1. 您必须致电 super(YourModelFormClass, self).clean() 以便检查唯一字段。
  2. 如果您正在编辑 cleaned_data,您还必须在附加到您的 ModelForm 的模型实例上编辑相同的字段:

    def clean(self)
      self.cleaned_data = super(MyModelFormClass, self).clean()
      self.cleaned_data['name']='My suggested value'
      self.instance.name = 'My suggested value'
      return self.cleaned_data
    

Documentation source for this behaviour

编辑:

与文档相反,我刚刚发现这不起作用。您必须编辑表单的 self.data 才能在表单显示时显示更改。

【讨论】:

  • 修改clean() 中的实例是个坏主意。这意味着执行if form.is_valid(): 会修改实例,这是完全出乎意料的行为。您应该在表单的save() 方法中修改实例,这就是它的目的。我会发布修改建议。
  • 除非您希望某些内容出现在您知道会失败或验证失败的表单中,在这种情况下,我希望建议值出现在字段,因此上述内容变得必要,因为没有其他方法可以实现目标,因为不会调用 save 方法。此外,在我的特定情况下,我确实需要访问两个字段。显然,如果只对一个字段进行操作,那么应该使用clean_<fieldname> 方法。
  • 您链接的文档是ModelFormSet 的文档,它的工作原理与ModelForm 大体相似,但有特定的怪癖,比如那个。不过没关系,因为在ModelFormSet 示例中修改的实例不是调用代码看到的实例。那个仍然保持不变,并没有打破is_valid() 除了编译错误列表之外没有副作用的期望。
  • 顺便说一句,如果你修改self.data,你应该小心,因为它可能是一个只读对象(例如django.http.QueryDict)。如果你想修改它,你应该在表单的构造函数中复制一份。
  • @spectras 首先,为什么cleaned_data 存在?因为is_valid() 有副作用。如果表单尚未经过验证,它会调用full_clean()clean() 以及所有这些(再次注意名称)。至少因为,在将值存储到数据库之前可能需要convert,然后返回...
【解决方案4】:

“这个方法应该返回从cleaned_data获得的清理值,不管它是否改变了任何东西。”来自https://docs.djangoproject.com/en/dev/ref/forms/validation/

【讨论】:

    猜你喜欢
    • 2011-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    相关资源
    最近更新 更多