【问题标题】:Django: Model clean method called before form cleanDjango:在表单清理之前调用模型清理方法
【发布时间】:2018-05-10 16:20:43
【问题描述】:

我不明白,为什么我的模型clean 方法在完整的表单验证之前被调用。

我的表单中有必填字段。如果我不填写它们,我不会收到表单错误,而是调用模型清理方法(所以我想这是因为调用了 save)。

它在模型clean() 方法中崩溃:

if self.date_from > self.date_to

无法将 datetime.date 与 NoneType 进行比较

因为我没有填写date_to 字段。我认为该表单应该处理它并提高ValidationError 和模型save() 甚至不应该被调用。

创建视图应该继承form_invalid方法。

class TripCreationForm(forms.ModelForm):
    date_from = forms.DateField(required=True)
    date_to = forms.DateField(required=True)
    place_id = forms.CharField(widget=forms.HiddenInput(),required=True)


    class Meta:
        model = Trip
        fields = ['date_from','date_to','detail','participants','place_id']

    def __init__(self, *args,**kwargs):
        user = kwargs.pop('user')
        super(TripCreationForm, self).__init__(*args,**kwargs)
        fs_helpers.add_widget_attribute('class','datepicker',self.fields['date_from'])
        fs_helpers.add_widget_attribute('class','datepicker',self.fields['date_to'])
        self.instance.user = user

    def clean(self):

        cleaned_data = super(TripCreationForm,self).clean()
        city, created = City.objects.get_or_create(place_id=self.cleaned_data['place_id'])
        self.instance.city = city
        date_from = self.cleaned_data.get('date_from')
        date_to = self.cleaned_data.get('date_to')
        if date_from and date_to and date_from>=date_to:
            raise ValidationError(_('Date from can\'t be higher that date to'))

        return cleaned_data

这是我的看法:

class TripCreationView(SuccessMessageMixin,CreateView):
    form_class = TripCreationForm
    template_name = 'trips/add_new_trip.html'
    success_message = _('Congratulations! You\'ve added a new trip!')
    context_object_name = 'trip_creation_form'

    def post(self, request, *args, **kwargs):  # TODO Switch to get_success_url
        return super(TripCreationView, self).post(self, request, *args, **kwargs)

    def get_form_kwargs(self):
        kwargs = super(TripCreationView, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def get_context_data(self, **kwargs):
        context=  super(TripCreationView,self).get_context_data(**kwargs)
        context['trip_creation_form'] = context['form']
        return context

    def get_success_url(self):
        return self.request.POST.get('success_url') or reverse('frontend:homepage'

)

这是模型的一部分:

def save(self, *args, **kwargs):
    created = not (bool(self.pk))
    self.full_clean()
    with transaction.atomic():
        Trip.objects.stretch_trips(self)
        super(Trip, self).save(*args, **kwargs)

def clean(self):
    if self.date_from > self.date_to: # HERE IT CRASHES
        raise ValidationError(_("Date to can't be lower than date from"))

问题出在哪里?为什么没有引发表单清理错误?

【问题讨论】:

    标签: django forms django-models django-forms


    【解决方案1】:

    model form is validated 时,它会为模型运行clean 方法。如果您查看未包含的完整回溯,那么我认为您会看到错误发生在视图调用 form.is_valid() 时,而不是在保存表单时。

    在模型的 clean 方法中,您应该检查是否设置了 self.date_fromself.date_to,类似于表单的 clean 方法。

    class Trip(models.Model):
        def clean(self):
            if self.date_from and self.date_to and self.date_from > self.date_to:                 raise ValidationError(_("Date to can't be lower than date from"))
    

    您可以从表单的clean 方法中删除检查,以防止重复。

    【讨论】:

    • 谢谢。 Date_from 和 date_to 是必需的模型字段,所以我认为在模型清理之前对其进行检查。
    猜你喜欢
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    相关资源
    最近更新 更多