Reputation: 4124
I have model
@with_author
class Lease(CommonInfo):
version = IntegerVersionField( )
is_renewed = models.BooleanField(default=False)
unit = models.ForeignKey(Unit)
is_terminated = models.BooleanField(default=False)
def __unicode__(self):
return u'%s %i %s ' % ("lease#", self.id, self.unit)
def clean(self):
model = self.__class__
if self.unit and (self.is_active == True) and model.objects.filter(unit=self.unit, is_terminated = False , is_active = True).count() == 1:
raise ValidationError('Unit has active lease already, Terminate existing one prior to creation of new one or create a not active lease '.format(self.unit))
and I have a form
class LeaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LeaseForm, self).__init__(*args, **kwargs)
self.fields['unit'].required = True
class Meta:
model = Lease
fields = [ 'unit',
'is_active','is_renewed', 'description']
and each time a save this form without selecting value for unit I am getting
error RelatedObjectDoesNotExist
from my clean function in model since there is no self.unit
but I am explicitly validating the unit field.(at least i believe so)
what am I doing wrong?
Upvotes: 1
Views: 712
Reputation: 2671
Note that full_clean() will not be called automatically when you call your model’s save() method. You’ll need to call it manually when you want to run one-step model validation for your own manually created models. [docs]
This is apparently done for backwards compatibility reasons, check this ticket out.
Model's full_clean()
method is responsible for calling Model.clean()
, but because it's never been called, your clean method inside model is basically omitted.
You can do couple of things for this. You can call model's clean manually. Or, you can move your validation logic into ModelForm using its clean methods. If you are mainly creating instance via form, I think it's the best place to perform validation (and more common practice).
Try this:
class LeaseForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LeaseForm, self).__init__(*args, **kwargs)
self.fields['unit'].required = True
# IF your validation logic includes multiple fields override this
def clean(self):
cleaned_data = super(LeaseForm, self).clean()
# .. your logic
return cleaned_data
# IF just your field's value is enough for validation override this
def clean__unit(self):
data = self.cleaned_data.get('unit', None)
# .. your logic
return data
class Meta:
model = Lease
fields = [ 'unit',
'is_active','is_renewed', 'description']
Upvotes: 1