Как сравнить две даты в базе данных так, чтобы следующая начиналась с предыдущей?
У меня есть модель "Образование", где пользователь должен ввести годы обучения в университете. Поэтому я просто хочу, чтобы, когда пользователь добавляет год начала обучения, год окончания обучения не мог быть меньше года начала обучения и должен быть в пределах +10 лет от года начала обучения.
Сейчас мои модели выглядят так:
Мои модели:
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Education(models.Model):
name_university=models.CharField('University',max_length=300, blank=True)
degree_of_edu=models.CharField('Degree of Education', max_length=25, blank=True)
start_year=models.IntegerField('Start year',default=current_year(), validators=[MinValueValidator(1945), max_value_current_year])
end_year=models.IntegerField('End year', default=current_year()+1,validators=[MinValueValidator(1945), MaxValueValidator(2100)])
speciality=models.CharField('Speciality', default='Engineer', max_length=250, blank=True)
def __str__(self):
return '{}'.format(self.name_university)
Я понял, что IntegerFields не могут сравниваться друг с другом, потому что я уже получил ошибку, подобную этой:
'>' не поддерживается между экземплярами 'int' и 'IntegerField'
Так, например: если вы выбрали или написали: 2021, вы сможете выбрать конец обучения только 2022-2031
Или это вообще возможно сделать только на этапе формы?
Вы можете работать с clean()
и фреймворком ограничений Django для обеспечения этого. Кроме того, вы допустили несколько ошибок относительно значения по умолчанию для годов: это должна быть ссылка на вызываемую переменную , а не на результат этой переменной, иначе, если ваш сервер будет работать между 31 декабря и 1 января, он вернет старый год.
from django.core.exceptions import ValidationError
from django.db.models import F, Q
from django.utils.timezone import now
def current_year():
return now().year
def default_end_year():
return current_year()+1
def max_value_current_year(value):
if value > current_year():
raise ValidationError('The year can not be greater than the current year.')
class Education(models.Model):
# ⋮
start_year=models.IntegerField(
'Start year',
default=current_year,
validators=[MinValueValidator(1945), max_value_current_year]
)
end_year=models.IntegerField(
'End year',
default=default_end_year,
validators=[MinValueValidator(1945), MaxValueValidator(2100)]
)
def clean(self, *args, **kwargs):
if self.end_year < self.start_year:
raise ValidationError('The end year can not be less than the start_year', code='end_year_too_low')
if self.end_year > self.start_year+10:
raise ValidationError('The end year should be at most ten years after the start year', code='study_too_long')
return super().clean(*args, **kwargs)
class Meta:
constraints = [
models.CheckConstraint(check=Q(end_year__gte=F('start_year')), name='end_year_too_low'),
models.CheckConstraint(check=Q(end_year__lte=F('start_year')+10), name='study_too_long')
]
Метод constraints = [ … ]
будет применять ограничения на уровне базы данных, если база данных поддерживает это. Метод .clean(…)
[Django-doc] будет запущен, если вы используете ModelForm
, или вы можете вручную очистить объект модели перед попыткой его сохранения.