【问题标题】:Django forms - how to override field validationDjango 表单 - 如何覆盖字段验证
【发布时间】:2015-08-06 02:40:17
【问题描述】:

在表单中,我有某些字段未正确验证。我希望覆盖 django 验证并使用我自己的验证。当我覆盖 clean() 方法时,字段 self.errors 已经填充了来自错误验证字段的错误。我应该重写哪个方法,这些错误是在哪里生成的?

通过覆盖clean() 和类似的方法,可以实现对django 默认验证的唯一扩展。我想阻止这种默认验证发生。

编辑:尝试过的验证器
这是我尝试过的:

253   def validate_gallery(value):
254     print 'validate galley'
255     return True
256   
257   def validate_cover_photo(value):
258     print 'validate_cf'
259     return True
260 
261   cover_photo_widget = SelectWithDefaultOptions(attrs={
262       'class': 'chosen-select-no-single',
263       'id': 'select-cover-photo',
264       'data-placeholder': 'Select Cover Photo',
265       'style': 'width: 200px;',
266       'tabindex': '-1',
267     });
268 
269   gallery_widget = SelectWithDefaultOptions(attrs={
270       'class': 'chosen-select-no-single',
271       'id': 'select-galley',
272       'data-placeholder': 'Select Gallery',
273       'style': 'width: 200px;',
274       'gallery-select': '',
275       'tabindex': '-1',
276       'organisator-profile-specific': '',
277     });
278   
279   gallery = forms.ChoiceField(widget = gallery_widget, validators = [validate_gallery])
280   cover_photo = forms.ChoiceField(widget = cover_photo_widget, validators = [validate_cover_photo])

甚至没有调用那些验证器。似乎寻求错误的过程在 validate() 函数调用处结束,这发生在调用任何验证器之前。

编辑:发布整个课程

240 def validate_gallery(value):
241   print 'validate galley'
242   return True
243 
244 def validate_cover_photo(value):
245   print 'validate_cf'
246   return True
247 
248 class EventDetailForm(NgFormValidationMixin, NgModelForm):
249   def __init__(self, *args, **kwargs):
250     super(EventDetailForm, self).__init__(*args, **kwargs)
251     self.fields['end_date'].required = False
252     self.fields['description'].required = False
253     self.fields['start_date'].input_formats = DATE_TIME_INPUT_FORMATS
254     self.fields['end_date'].input_formats = DATE_TIME_INPUT_FORMATS
255 
256     arguments_length = len(args)
257     if arguments_length > 0:
258       post_data = args[0]
259       self.old_title = post_data.get('old_title', None)
260 
261   cover_photo_widget = SelectWithDefaultOptions(attrs={
262       'class': 'chosen-select-no-single',
263       'id': 'select-cover-photo',
264       'data-placeholder': 'Select Cover Photo',
265       'style': 'width: 200px;',
266       'tabindex': '-1',
267     });
268 
269   gallery_widget = SelectWithDefaultOptions(attrs={
270       'class': 'chosen-select-no-single',
271       'id': 'select-galley',
272       'data-placeholder': 'Select Gallery',
273       'style': 'width: 200px;',
274       'gallery-select': '',
275       'tabindex': '-1',
276       'organisator-profile-specific': '',
277     });
278 
279   gallery = forms.ChoiceField(widget = gallery_widget, validators = [validate_gallery])
280   cover_photo = forms.ChoiceField(widget = cover_photo_widget, validators = [validate_cover_photo])
281 
282   class Meta:
283     model = Event
284     fields = ('title', 'description', 'end_date', 'start_date')
285     widgets = {
286       'title': forms.TextInput(attrs={
287         'editable-detail': '',
288       }),
289       'description': forms.TextInput(attrs={
290         'class': 'panel-body',
291         'id': 'event-description-editable',
292         'editable-detail': '',
293       }),
294       'start_date': DateTimeWidget(attrs = {
295         'class': 'datetimepicker col-xs-6',
296         'id': 'event-start-date-editable',
297         'editable-detail': '',
298       }),
299       'end_date': DateTimeWidget(attrs = {
300         'class': 'datetimepicker col-xs-6',
301         'id': 'event-end-date-editable',
302         'editable-detail': '',
303       }),
304     }
305 
306   def clean(self):
307     cleaned_data = self.cleaned_data
308 
309     print self.errors
310 
311     return cleaned_data
312     
313   def save(self, commit=True):
314     old_title = self.old_title
315     event = Event()
316 
317     cover_photo_title = self.cleaned_data['cover_photo']
318     cover_photo = Photo.objects.filter(title=cover_photo_title)
319     
320     gallery_title = self.cleaned_data['gallery']
321     gallery = Gallery.objects.filter(title=gallery_title)
322 
323     event.title = self.cleaned_data['title']
324     event.description = self.cleaned_data['desription']
325     event.start_date = self.cleaned_date['start_date']
326     event.end_date = self.cleaned_data['end_date']
327     event.cover_photo = cover_photo
328     event.gallery = gallery
329 
330     if commit:
331       event.save()
332       
333     return event
334 

clean() 中我可以看到错误存在,save() 永远不会执行。

【问题讨论】:

  • 函数是表单类定义的一部分吗?我认为验证器函数应该在类之外,否则它们需要两个输入参数(selfvalue),而它们应该只带一个。
  • @Tony 试图将它们放在课堂之外 - 结果相同。
  • 你能发布你的整个表单类吗?
  • @Tony 添加完成。
  • 您的表单继承自 NgFormValidationMixin 模型中的验证是否有任何可疑之处?

标签: python django validation django-forms


【解决方案1】:

为什么不编写自己的 Field 类,它有自己的 validate 方法,因为它在验证器本身之前被调用:

class MyCustomChoiceField(ChoiceField):

    def validate(self, value):
        <do something to validate your field>

然后使用它:

gallery = MyCustomChoiceField(widget = gallery_widget)

【讨论】:

  • 对于 ModelChoice,您需要覆盖 to_python 方法。
【解决方案2】:

除非一个字段的验证依赖于另一个字段的值,否则最好在表单字段定义中设置验证器函数。

来自Django documentation的示例:

from django import forms

class MyForm(forms.Form):
    even_field = forms.IntegerField(validators=[validate_even])

如果验证不是特定于表单的,您甚至可以在模型中设置验证器。

【讨论】:

  • 我试过了,还是达不到我想要的。检查我的编辑。
【解决方案3】:

您可以重写为清理数据而调用的 def clean_YOUR_VARIABLE_NAME 方法

参考:Cleaning a specific field attribute

例如:

class EmailForm(forms.Form):
    your_email = forms.EmailField(label='Your E-mail address', required=True)

    def clean_your_email(self):
        data = self.cleaned_data['your_email']
        # Check some condition over data
        # raise ValidationError for bad results
        # else return data

【讨论】:

  • 这些干净的技术提供了向默认技术添加额外验证的机会。我想避免使用默认的。
  • 在这种情况下,您不必在覆盖的方法中执行任何操作。 stackoverflow.com/questions/4340287/…
  • 想过,但@professorDante 的解决方案对我来说似乎更干净。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 1970-01-01
  • 2019-09-13
  • 1970-01-01
  • 2019-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多