Django模型的clean()方法没有提高各个字段的预期ValidationErrors

时间:2018-03-07 20:07:16

标签: python django validation

我有一个名为CheckIn的Django模型,其中包括两个字段min_weeksmax_weeks。我想建立验证,min_weeks始终小于或等于max_weeks。在https://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddo#django.db.models.Model.clean之后(特别是,ValidationError传递了一个将字段映射到错误的字典的最后一个示例),我尝试了以下clean()方法:

from django.db import models
from django.core.exceptions import ValidationError


class CheckIn(models.Model):
    min_weeks = models.IntegerField(blank=True, null=True)
    max_weeks = models.IntegerField(blank=True, null=True)

    def clean(self):
        if self.min_weeks > self.max_weeks:
            raise ValidationError({
                'min_weeks': ValidationError("'min_weeks' should be smaller than 'max_weeks'", code='invalid'),
                'max_weeks': ValidationError("'max_weeks' should be greater than 'min_weeks'", code='invalid')})

该模型用于ModelForm

class CheckInForm(forms.ModelForm):
    class Meta:
        model = CheckIn
        fields = [
            'min_weeks',
            'max_weeks',
        ]

字段在模板中手动显示。这是一段摘录:

<div class="row">
  <div class="input-field col s4">
    <div class="js-hide-edit-field-text {% if not check_in_type or form.min_weeks.value %}hide{% endif %}">
      {% if check_in_type and not form.min_weeks.value %}
        <span class='js-max-weeks inherited-field text'>{{ check_in_type.min_weeks }}</span>
        <a href='#' class='js-hide-edit-field-edit edit-icon right'><i class="material-icons">mode_edit</i></a>
        <label class="active">
          Min Weeks
        </label>
      {% endif %}
    </div>
    <div class="js-hide-edit-field {% if check_in_type and not form.min_weeks.value %}hide{% endif %}">
      {{ form.min_weeks|add_error_class:"invalid"|attr:"data-duration-weeks-mask" }}
      {{ form.min_weeks.errors }}
      {{ form.min_weeks|label_with_classes }}
    </div>
  </div>

  <div class="input-field col s4">
    <div class="js-hide-edit-field-text {% if not check_in_type or form.max_weeks.value %}hide{% endif %}">
      {% if check_in_type and not form.max_weeks.value %}
        <span class='js-min-weeks inherited-field text'>{{ check_in_type.max_weeks }}</span>
        <a href='#' class='js-hide-edit-field-edit edit-icon right'><i class="material-icons">mode_edit</i></a>
        <label class="active">
          Max Weeks
        </label>
      {% endif %}
    </div>
    <div class="js-hide-edit-field {% if check_in_type and not form.max_weeks.value %}hide{% endif %}">
      {{ form.max_weeks|add_error_class:"invalid"|attr:"data-duration-weeks-mask" }}
      {{ form.max_weeks.errors }}
      {{ form.max_weeks|label_with_classes }}
    </div>
  </div>
</div>

请注意,如果未明确提供CheckIn的{​​{1}},则可以在此处“继承”值。但总的来说,模板只显示CheckInTypeform.min_weeks以及相应的错误。

问题是,如果我为form.max_weeksmin_weeks输入了无效值,我会看到与我预期不同的错误消息(即“输入整数”而不是“'min_weeks'应小于'max_weeks'“):

enter image description here

这更令人费解,因为我输入了整数。知道问题可能在这里吗?

2 个答案:

答案 0 :(得分:1)

似乎传递code='invalid'关键字参数是导致它引发此默认错误消息的原因。如果我按如下方式修改Model.clean()方法:

def clean(self):
    if self.min_weeks > self.max_weeks:
        raise ValidationError({
            'min_weeks': ValidationError("'min_weeks' should be smaller than 'max_weeks'"),
            'max_weeks': ValidationError("'max_weeks' should be greater than 'min_weeks'")})

然后按预期显示错误:

enter image description here

顺便提一下,我跟踪这个问题的方法是查看Django IntegerField的源代码,它的开头是这样的:

class IntegerField(Field):
    widget = NumberInput
    default_error_messages = {
        'invalid': _('Enter a whole number.'),
    }

答案 1 :(得分:0)

在将字段分配给字段时,这不是您如何引发多个验证错误。您需要使用form.add_error()

 form.add_error('min_weeks', ValidationError("'min_weeks' should be smaller than 'max_weeks'", code='invalid'))
 form.add_error('max_weeks': ValidationError("'max_weeks' should be greater than 'min_weeks'", code='invalid'))