Why doesn't django's model.save() call full_clean()?
AFAIK, this is because of backwards compatibility. There are also problems with ModelForms with excluded fields, models with default values, pre_save() signals, etc.
Sources you might be intrested in:
- http://code.djangoproject.com/ticket/13100
- http://groups.google.com/group/django-developers/browse_frm/thread/b888734b05878f87
Problems when calling self.full_clean() in model save()
I found a solution by defining class DefaultUserFactory
this way:
class DefaultUserFactory(factory.DjangoModelFactory):
first_name = factory.Faker('first_name')
last_name = factory.Faker('last_name')
date_of_birth = factory.fuzzy.FuzzyDate(start_date=date(year=1900, month=1, day=1))
gender = User.GENDER_OTHER
slug = factory.fuzzy.FuzzyText(chars=string.ascii_lowercase)
username = factory.LazyAttribute(lambda o: normalize_username(slug=o.slug))
password = factory.fuzzy.FuzzyText(chars=string.ascii_lowercase)
_password = factory.PostGenerationMethodCall(method_name='set_password', raw_password=USER_PASSWORD)
class Meta:
model = User
django save(commit=False) versus full_clean
Calling full_clean()
is the correct way to validate a model instance.
from django.core.exceptions import ValidationError
try:
obj.full_clean()
except ValidationError:
# handle invalid object
When dealing with a model form, calling is_valid()
will perform the model validation, so you don't have to call full_clean()
manually.
Calling save()
with commit=False
doesn't perform model validation. Instead, it gives you the opportunity to change the object before you save it to the database. A common example is to set the user attribute to the user that is currently logged on.
Django doesn't call model clean method
I've found a solution to override method:
class CommonMeasurement(models.Model):
timestamp = models.DateTimeField()
value = models.FloatField()
run = models.ForeignKey(Run)
objects = models.Manager()
analyzes = managers.MeasureStatManager()
def save(self, **kwargs):
self.clean()
return super(CommonMeasurement, self).save(**kwargs)
def clean(self):
super(CommonMeasurement, self).clean()
print 'here we go'
if self.timestamp < self.run.timestamp_start or self.timestamp > self.run.timestamp_end:
raise django_excetions.ValidationError('Measurement is outside the run')
But I'm not sure that it can be a good decision.
Django model validation not raising Exception on full_clean()
A validator should raise a ValidationError
in case the condition is not met, not return True
or False
, so:
from django.core.exceptions import ValidationError
def home_away_valid(value):
if value not in ('H', 'A'):
raise ValidationError('Must be home or away')
You also might want to use 'H'
and 'A'
as choices, this will render the form with a ChoiceField
, making it less likely to make mistakes:
class Team(models.Model):
HOME_AWAY = (
('H', 'Home'),
('A', 'Away')
)
name = models.CharField(max_length=180)
home = models.CharField(max_length=2, choices=HOME_AWAY, validators=[home_away_valid], default='H', db_index=True)
Related Topics
Split a List into Nested Lists on a Value
Understanding .Get() Method in Python
Changing Order of Unit Tests in Python
Python Saving Multiple Figures into One PDF File
How to Log Server Errors on Django Sites
Which Seeds Have to Be Set Where to Realize 100% Reproducibility of Training Results in Tensorflow
Distributing My Python Scripts as Jar Files with Jython
How to Upload a File to Google Cloud Storage on Python 3
Why Is the Empty Dictionary a Dangerous Default Value in Python
Duplicate Items in Legend in Matplotlib
I'm Getting "Typeerror: 'List' Object Is Not Callable". How to Fix This Error
How to Change UI in Same Window Using Pyqt5
Write Dictionary of Lists to a CSV File
How to Fix "Importerror: Dll Load Failed" While Importing Win32Api
Remove None Value from a List Without Removing the 0 Value
Import CSV with Different Number of Columns Per Row Using Pandas
Add Column with Number of Days Between Dates in Dataframe Pandas
Python:When Is a Variable Passed by Reference and When by Value