I have a problem with a model's clean()
method and basic field validation. here's my model and the clean()
method.
class Trial(models.Model):
trial_start = DurationField()
movement_start = DurationField()
trial_stop = DurationField()
def clean(self):
from django.core.exceptions import ValidationError
if not (self.movement_start >= self.trial_start):
raise ValidationError('movement start must be >= trial start')
if not (self.trial_stop >= self.movement_start):
raise ValidationError('trial stop must be >= movement start')
if not (self.trial_stop > self.trial_start):
raise ValidationError('trial stop must be > trial start')
My clean()
method checks whether certain values are in the correct range. If the user forget to fill out a field, e.g. movement_start
, then I get an error:
can't compare datetime.timedelta to NoneType
I'm surprised that I get this error, since the original clean()
function should be catching that missing entry (after all movement_start
is a required field). So how can I the basic checking for missing values, and my custom check whether values are in certain ranges? Can this be done with model's clean()
method, or do I need to use Forms
?
EDIT1 to make it more clear: trial_start
, movement_start
and trial_stop
are all required fields. I need to write a clean()
method which first checks that all three fields have been filled out, and then, check whether the values are in a certain range.
The following code for example DOES NOT work, since trial_start
might be empty. I want to avoid having to check for the existence of each field - django should do that for me.
class TrialForm(ModelForm):
class Meta:
model = Trial
def clean_movement_start(self):
movement_start = self.cleaned_data["movement_start"]
trial_start = self.cleaned_data["trial_start"]
if not (movement_start >= trial_start):
raise forms.ValidationError('movement start must be >= trial start')
return self.cleaned_data["movement_start"]
EDIT2 The reason that I wanted to add this check to the model's clean()
method is that objects that are created on the python shell, will automatically be checked for correct values. A form will be fine for views, but I need the value check also for the shell.
cleaned_data is where all validated fields are stored.
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.
Field validation is an automated process of ascertaining that each field contains the correct value before the form is accepted. The concept is straightforward.
If yes try to disable this behavior, set the novalidate attribute on the form tag As <form action="{% url 'new_page' %}", method="POST" novalidate> in your html file.
I guess that's the way to go:
class TrialForm(ModelForm):
class Meta:
model = Trial
def clean(self):
data = self.cleaned_data
if not ('movement_start' in data.keys() and 'trial_start' in data.keys() and 'trial_stop' in data.keys()):
raise forms.ValidationError("Please fill out missing fields.")
trial_start = data['trial_start']
movement_start = data['movement_start']
trial_stop = data['trial_stop']
if not (movement_start >= trial_start):
raise forms.ValidationError('movement start must be >= trial start')
if not (trial_stop >= movement_start):
raise forms.ValidationError('trial stop must be >= movement start')
if not (trial_stop > trial_start):
raise forms.ValidationError('trial stop must be > trial start')
return data
EDIT the downside of this approach is, that value checking will only work if I create objects through the form. Objects that are created on the python shell won't be checked.
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