Метод clean() в модели и проверка поля
У меня проблема с методом модели clean()
и базовой проверкой поля. здесь моя модель и метод clean()
.
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')
Мой метод clean()
проверяет, находятся ли определенные значения в правильном диапазоне. Если пользователь забыл заполнить поле, например. movement_start
, я получаю сообщение об ошибке:
can't compare datetime.timedelta to NoneType
Я удивлен, что получаю эту ошибку, так как исходная функция clean()
должна улавливать эту пропущенную запись (ведь movement_start
- обязательное поле). Итак, как я могу выполнить базовую проверку отсутствующих значений, и моя пользовательская проверка, находятся ли значения в определенных диапазонах? Можно ли это сделать с помощью метода модели clean()
, или мне нужно использовать Forms
?
EDIT1, чтобы сделать его более понятным: trial_start
, movement_start
и trial_stop
- все обязательные поля. Мне нужно написать метод clean()
, который сначала проверяет, что все три поля заполнены, а затем проверьте, находятся ли значения в определенном диапазоне.
Следующий код, например, НЕ работает, поскольку trial_start
может быть пустым. Я хочу избежать необходимости проверять наличие каждого поля - django должен сделать это для меня.
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 Причина, по которой я хотел добавить эту проверку в метод модели clean()
, заключается в том, что объекты, созданные в оболочке python, будут автоматически проверяться на правильные значения. Форма будет полезна для представлений, но мне нужна проверка значения и для оболочки.
Ответы
Ответ 1
Я предполагаю, что путь:
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 Недостатком этого подхода является то, что проверка значения будет работать, только если я создам объекты через форму. Объекты, созданные на оболочке python, не будут проверяться.
Ответ 2
Я знаю, что это уже поздно, но чтобы ответить, почему это может произойти для людей, которые здесь заканчиваются: нет "оригинальной чистой". Чистый метод - это крючок для пользовательской проверки, поэтому вы являетесь тем, кто предоставляет свой код. Не знаете, как OP использует чистый крючок, но: после его определения вы должны называть full_clean()
над вашими моделями, чтобы Django полностью выполняла проверку модели. См. Подробности в документах для порядка, в котором он вызывает различные методы проверки, и https://docs.djangoproject.com/en/1.11/ref/models/instances/#validating-objects (возможно, важно отметить: full_clean()
автоматически не вызывается моделью save()
, которая является частью того, почему, когда вы используете оболочку и сохраняете сразу же, вы пропустите проверку)
(примечание ModelForms также имеют различные этапы проверки и вызовет модель full_clean: https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#validation-on-a-modelform)
Ответ 3
Я борюсь с подобной проблемой, но с ForeignKey
. В вашем случае я просто проверю, что поля не пусты, и я упростил бы ваши булевы выражения:
class Trial(models.Model):
trial_start = DurationField()
movement_start = DurationField()
trial_stop = DurationField()
def clean(self):
from django.core.exceptions import ValidationError
if self.trial_start:
if self.movement_start and self.movement_start < self.trial_start:
raise ValidationError('movement start must be >= trial start')
if self.trial_stop:
if self.trial_stop <= self.trial_start:
raise ValidationError('trial stop must be > trial start')
if self.movement_start:
if self.trial_stop < self.movement_start:
raise ValidationError('trial stop must be >= movement start')