Django:在表单清理之前调用模型清理方法 [英] Django: Model clean method called before form clean

查看:77
本文介绍了Django:在表单清理之前调用模型清理方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我在表单中有必填字段。如果不填写,就不会出现表格错误,而是会调用模型清理方法(因此,我想是因为调用了 save )。 / p>

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

 如果self.date_from> self.date_to 




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


因为我没有填写 date_to 字段。我认为该表单应该可以处理它并引发 ValidationError ,甚至不应该调用模型 save()。 / p>

创建视图应继承 form_invalid 方法。

 类TripCreationForm(forms.ModelForm):
date_from =表单.DateField(必需=真)
date_to =表单.DateField(必需=真)
place_id = form.CharField(widget = forms.HiddenInput(),required = True)


类元:
模型=行程
字段= ['date_from',' date_to','detail','参与者','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 =用户

def clean(self):

cleaned_data = super(TripCreationForm,self).clean()
城市,创建= City.objects.get_or_create(place_id = self.cleaned_data ['place_id'])
self.instance.city =城市
date_from = self.cleaned_data.get('date_from')
date_to = self.cleaned_data.get('date_to')
如果date_from和date_to和date_from> = date_to:
引发ValidationError(_('起始日期不能比该日期高)'

返回cleaned_data

这是我的观点:

  class TripCreationView(SuccessMessageMixin,CreateView):
form_class = TripCreationForm
template_name ='trips / add_new_trip.html'
success_message = _('恭喜!您已添加新行程!')
context_object_name ='trip_creation_form'

def post(自己,请求,* args,** kwargs):#TODO切换至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
返回kwargs

def get_context_data(self,** kwargs):
context = super(TripCreationView,self).get_context_data(** kwargs)
context ['trip_creation_form'] = context ['form']
返回上下文

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



这是模型的一部分:

  def save(self,* args,** kwargs):
创建=不(bool(self.pk))
self.full_ clean()
with transaction.atomic():
Trip.objects.stretch_trips(self)
super(旅行,self).save(* args,** kwargs)

def clean(self):如果self.date_from> self.date_to:#这里会崩溃
引发ValidationError(_(日期不能低于日期,))

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

解决方案

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



在模型的干净方法中,应检查 self.date_from 和<$设置了c $ c> self.date_to ,类似于表单的清理方法。

  class Trip (models.Model):
def clean(self):
,如果self.date_from和self.date_to以及self.date_from> self.date_to:引发ValidationError(_(日期不能低于起始日期))

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


I don't understand, why is my model clean method called before full form validation.

I have required fields in my form. If I don't fill them, I don't get form errors, instead of, the model clean method is called (so I suppose it's because save is called).

It crashes in models clean() method:

if self.date_from > self.date_to

can't compare datetime.date to NoneType

Because I didn't filled date_to field. I think that form should have handle it and raise ValidationError and models save() shouldn't be even called.

Create view should inherit form_invalid method.

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

This is my view:

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'

)

And this is part of the model:

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"))

Where is the problem? Why there is no form clean error raised?

解决方案

When a model form is validated, it runs the clean method for the model. If you look at the full traceback, which you haven't included, then I think you'll see that the error occurs when the view calls form.is_valid(), not when the form is saved.

In your model's clean method, you should check that self.date_from and self.date_to are set, similar to your form's clean method.

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"))

You could remove the check from the form's clean method, to prevent duplication.

这篇关于Django:在表单清理之前调用模型清理方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆