Why Doesn't Django's Model.Save() Call Full_Clean()

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



Leave a reply



Submit