As I understand it, when one creates a Django application, data is validated by the form before it's inserted into a model instance which is then written to the database. But if I want to create an additional layer of protection at the data model layer, is what I've done below the current "best practice?" I'm trying to ensure that a reviewer's name cannot be omitted nor be left blank. Should I be putting any custom validation in the 'clean' method as I've done here and then have 'save' call 'full_clean" which calls 'clean'? If not, what's the preferred method? Thanks.
class Reviewer(models.Model): name = models.CharField(max_length=128, default=None) def clean(self, *args, **kwargs): if self.name == '': raise ValidationError('Reviewer name cannot be blank') super(Reviewer, self).clean(*args, **kwargs) def full_clean(self, *args, **kwargs): return self.clean(*args, **kwargs) def save(self, *args, **kwargs): self.full_clean() super(Reviewer, self).save(*args, **kwargs)
to_python() method of the models. Field subclass (obviously for that to work you must write custom fields). Possible use cases: when it is absolutely neccessary to ensure, that an empty string doesn't get written into the database (blank=False keyword argument doesn't work here, it is for form validation only)
Django forms submit only if it contains CSRF tokens. It uses uses a clean and easy approach to validate data. The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.
They go into a special “field” (called all), which you can access via the non_field_errors() method if you need to. If you want to attach errors to a specific field in the form, you need to call add_error(). So from Django documentation you can use add_error() to do what you want to achieve.
clean_fields() method documentation: This method will validate all fields on your model. The optional exclude argument lets you provide a list of field names to exclude from validation. It will raise a ValidationError if any fields fail validation.
Firstly, you shouldn't override full_clean
as you have done. From the django docs on full_clean:
Model.full_clean(exclude=None)
This method callsModel.clean_fields()
,Model.clean()
, andModel.validate_unique()
, in that order and raises aValidationError
that has amessage_dict
attribute containing errors from all three stages.
So the full_clean
method already calls clean
, but by overriding it, you've prevented it calling the other two methods.
Secondly, calling full_clean
in the save
method is a trade off. Note that full_clean
is already called when model forms are validated, e.g. in the Django admin. So if you call full_clean
in the save
method, then the method will run twice.
It's not usually expected for the save method to raise a validation error, somebody might call save
and not catch the resulting error. However, I like that you call full_clean
rather than doing the check in the save method itself - this approach allows model forms to catch the problem first.
Finally, your clean
method would work, but you can actually handle your example case in the model field itself. Define your CharField
as
name = models.CharField(max_length=128)
The blank
option will default to False. If the field is blank, a ValidationError
will be raised when you run full_clean
. Putting default=None
in your CharField
doesn't do any harm, but it is a bit confusing when you don't actually allow None
as a value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With