Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django forms - how to override field validation

In a form I have certain fields, that are not validated correctly. I wish to override the django validation and put my own instead. When I override the clean() method, the field self.errors is already filled with errors from the wrongly validated fields. Which method should I override, where are these errors generated?

With overriding clean() and similar methods, one can achieve only extension to the django default validation. I want to prevent this default validation from happening.

Edit: tried validators
Here is what I tried:

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

Those validators are not even called. Seems like the error-seeking process ends at the validate() function call, which happens before any validators are called.

Edit: posting the whole class

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 

In clean() I can see that the errors are there, save() is never executed.

like image 975
victor175 Avatar asked May 24 '15 14:05

victor175


1 Answers

Why not write your own Field class, that has its own validate method, as this is called before the validator itself:

class MyCustomChoiceField(ChoiceField):

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

then use it:

gallery = MyCustomChoiceField(widget = gallery_widget)
like image 109
professorDante Avatar answered Oct 07 '22 02:10

professorDante