Django:在表单清理之前调用模型清理方法 [英] Django: Model clean method called before form clean
问题描述
我不明白,为什么在进行完整表单验证之前调用模型 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屋!