Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design-- www.djangoproject.com
Using Django Model Form can make it fast and powerful to validate input data. But new Django programmer can be confused between form validation and model validation. Both of these are defined in models.py
class Report(models.Model):
name = models.CharField(_('Name'), max_length=20, blank=False, null=False, default=None)
When you define "null=False" and "blank=False" to the model field, let see what you will get?
"null = False", sure thing that it's gonna raise IntegrityError when you try to save but didn't assign value to the field.
"blank=False", Do you suppose that it's gonna work at model level?
If so, you will be disappointed because "blank=False" will take effect only at form level. Means that you can save the instance using the shell.
(InteractiveConsole)
>>> from report.models import Report
>>> new_report = Report()
>>> new_report.save()
>>> Traceback (most recent call last):
...
>>> IntegrityError: report_report.name may not be NULL
Assign blank name.
>>> new_report.name = ''
>>> new_report.save()
Now you get the Report object with blank in the name field in the database!
To avoid this, let's create the helper:
from django.db import IntegrityError
def not_null_not_blank(instance, attribute_name_iter ):
for attribute_name in attribute_name_iter:
if not getattr(instance, attribute_name):
raise IntegrityError('%s.%s may not be NULL or BLANK' % (instance.__class__.__name__, attribute_name )) #This line is inspired by Nattapon (@wrongite)
And override your model's save function:
class Report(models.Model):
name = models.CharField(_('Name'), max_length=20, blank=False, null=False, default=None)
def save(self, force_insert=False, force_update=False):
not_null_not_blank(self,('name', ))
return super(Report , self).save(force_insert=force_insert, force_update=force_update)
Now exit the shell and open it again ( to reload new code you've just changed )
(InteractiveConsole)
>>> from report.models import Report
>>> another_report = Report()
>>> another_report.name=''
>>> another_report.save()
>>> Traceback (most recent call last):
...
>>> IntegrityError: Report.name may not be NULL or BLANK
Now you're good to go!! ; )

Why not make it into a decorator instead?
Using decorator is a good idea. ;)
I will add this to the entry. Thank you.