【问题标题】:Django - How best to handle ValidationErrors after form.save(commit=False)Django - form.save(commit=False) 之后如何最好地处理 ValidationErrors
【发布时间】:2011-02-02 17:54:15
【问题描述】:

这是我的代码片段:

    if form.is_valid():
        instance = form.save(commit=False)
        try:
            instance.account = request.account
            instance.full_clean()
        except ValidationError, e:
            # Do something with the errors here... I certainly don't want to do this 180 times.

这真是一团糟。谁愿意在每个视图中手动处理验证错误。如果您在save(commit=False) 之后没有修改实例,则不必担心这一点,但在我的情况下,每个模型都有一个指向account 的外键,该外键设置在幕后并且对用户?

非常感谢任何帮助。

【问题讨论】:

    标签: django django-models django-forms django-validation


    【解决方案1】:

    由于问题上的标签,我假设formModelForm

    由于ModelForm performs model validation when you call is_valid(),在调用is_valid() 之前,确保它将验证的模型实例已经包含您想要进行的任何幕后更改就足够了。

    您可以通过在调用 is_valid() 之前使用您的更改修改 form.instance 来做到这一点。

    在表单本身内进行此类更改的更通用的解决方案是:

    class PresetAttrsModelForm(ModelForm):
        def __init__(self, *args, **kwargs):
            preset_attrs = kwargs.pop('preset_attrs', None)
            # Sets up self.instance, among other things
            super(ModelForm, self).__init__(*args, **kwargs)
            if preset_attrs:
                for attr, value in preset_attrs.items():
                    setattr(self.instance, attr, value)
    
    class MyModelForm(PresetAttrsModelForm):
        class Meta:
            model = MyModel
    
    form = MyModelForm(preset_attrs={'account': request.account})
    

    【讨论】:

    • @insin +1 谢谢!我之前以为只有在调用instance = save(commit=False) 之后才能访问实例。我还有一个问题要问您:如果我手动添加属性,这意味着我可能不会将它们包含在表单中(即使由于安全性而被隐藏)。在这种情况下,Django 不会使用 is_valid() 验证这些字段,因为它们被“排除”了。即使它们被“排除”,我如何将它们包含在验证过程中,这样我就不必手动捕获错误并使用form._update_errors()
    【解决方案2】:

    不确定是否正确理解您的问题,但如果您想“集中”验证表单中的数据,您可以覆盖表单的 clean() 方法:

    django docs - overwrite clean method

    为了根据表单中传递的数据更改对象的数据,您可以覆盖 form.save 方法:

    SOF discussion - overwrite save method

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-03
      • 2013-06-13
      • 2014-01-28
      • 2021-06-16
      相关资源
      最近更新 更多