#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 [email protected].
To post to this group, send email to [email protected].
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.