#22921: Model.clean_fields incorrectly skips validation for fields where null value is not allowed -------------------------------------+------------------------------------- Reporter: silveroff@… | Owner: nobody Type: | Status: new Cleanup/optimization | Version: master Component: Database layer | Resolution: (models, ORM) | Triage Stage: Severity: Normal | Unreviewed Keywords: field validation, | Needs documentation: 0 model | Patch needs improvement: 0 Has patch: 0 | UI/UX: 0 Needs tests: 0 | Easy pickings: 0 | -------------------------------------+-------------------------------------
Comment (by anonymous): Sure, {{{ # Model class Example(models.Model): optional_decimal = models.DecimalField( blank=True, null=False, # so I want this field to be optional in my forms, but I dont want null values in db default=Decimal(0), validators=[MinValueValidator(0)], max_digits=8, decimal_places=2, ) # Form class ExampleForm(ModelForm): class Meta: model = Example }}} Now if one create object using this form without providing value for optional_decimal field this would result in IntegrityError: (1048, "Column 'optional_decimal' cannot be null") So developer has to create ExampleForm.clean_optional_decimal method to handle this issue, and thats not DRY and wouldn't be needed if model.clean_fields run validation at the first place. Something like this would suffice: {{{ def clean_fields(self, exclude=None): """ Cleans all fields and raises a ValidationError containing message_dict of all validation errors if any occur. """ if exclude is None: exclude = [] errors = {} for f in self._meta.fields: if f.name in exclude: continue # Skip validation for empty fields with blank=True. The developer # is responsible for making sure they have a valid value. raw_value = getattr(self, f.attname) if f.blank and raw_value in f.empty_values: # do not skip validation if raw_value is None and field does not accept null values to be saved! if raw_value is None and not f.null: pass else: continue try: setattr(self, f.attname, f.clean(raw_value, self)) except ValidationError as e: errors[f.name] = e.error_list if errors: raise ValidationError(errors) }}} -- Ticket URL: <https://code.djangoproject.com/ticket/22921#comment:2> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/077.8ee2ceb17dfa674cd20f2f1313dd2866%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.