KeyError при выборе даты в прошлом
Я делаю приложение для управления членами. У меня есть форма активации и я написал скрипт для проверки правильности даты (clean_start_date & clean_end_date). т.е. сегодняшняя дата или больше. Скрипт работает нормально (если я выбираю сегодняшнюю дату или больше). Однако, если я выбрал старую дату, только end_date работает нормально, start_date бросает KeyError.
forms.py
class ActiveMemberForm(ModelForm):
def __init__(self, *args, **kwargs):
super(ActiveMemberForm, self).__init__(*args, **kwargs)
pass
class Meta:
model = ActiveMember
fields = (
'member',
'start_date',
'end_date',
'status',
)
widgets = {
'start_date': widgets.DateInput(attrs={'type': 'date'}),
'end_date': widgets.DateInput(attrs={'type': 'date'}),
}
def clean_start_date(self):
start_date = self.cleaned_data['start_date']
if start_date < timezone.now().date():
raise ValidationError('Please enter a valid start date!')
return start_date
def clean_end_date(self):
#start_date = self.cleaned_data['start_date']
end_date = self.cleaned_data['end_date']
if end_date < timezone.now().date() or end_date < self.clean_start_date():
raise ValidationError('Please enter a valid end date!')
return end_date
models.py
class ActiveMember(models.Model):
member = models.OneToOneField(Member, on_delete=models.CASCADE, related_name='is_member')
start_date = models.DateField(default=django.utils.timezone.now)
end_date = models.DateField(default=django.utils.timezone.now)
status = models.CharField(max_length=2, choices=(('1','Active'), ('2','Inactive')), default = '1', blank=True, null=True)
def __str__(self):
return str(f"{self.member}")
Сообщение об ошибке консоли
Internal Server Error: /activate/
Traceback (most recent call last):
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\core\handlers\exception.py", line 55, in inner
response = get_response(request)
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\django_project\members\views.py", line 130, in activate
if form.is_valid():
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\forms\forms.py", line 205, in is_valid
return self.is_bound and not self.errors
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\forms\forms.py", line 200, in errors
self.full_clean()
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\forms\forms.py", line 437, in full_clean
self._clean_fields()
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\lib\site-packages\django\forms\forms.py", line 452, in _clean_fields
value = getattr(self, "clean_%s" % name)()
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\django_project\members\forms.py", line 58, in clean_end_date
if end_date < timezone.now().date() or end_date < self.clean_start_date():
File "C:\Users\timmeh\source\Python Projects\Django Projects\env\django_project\members\forms.py", line 49, in clean_start_date
start_date = self.cleaned_data['start_date']
KeyError: 'start_date'
[12/Aug/2022 14:55:53] "POST /activate/ HTTP/1.1" 500 89452
Скриншот отладочной программы KeyError
Ошибка, которую вы получаете, связана с тем, что метод clean_start_date()
вызывается при валидации формы, а это:
if start_date < timezone.now().date():
raise ValidationError('Please enter a valid start date!')
Исключает поле из проверки данных, делая форму недействительной. Поэтому, вероятно, вы не получите данные в self.cleaned_field['start_date']
Также я не совсем понимаю, почему вы вызываете clean_start_date
дважды - этот метод вызывается один раз невидимым образом формой, второй - вами. Когда вы пишете методы clean_FIELD_NAME
, они вызываются непосредственно логикой формы Django.
Итак... простой и наиболее очевидный способ решить вашу проблему - написать clean_end_date()
метод правильно, без вызова чистых методов:
start_date = self.cleaned_data['start_date']
end_date = self.cleaned_data['end_date']
# not necessary data clean on start date field
# if end_date < timezone.now().date() or end_date < self.clean_start_date():
if end_date < timezone.now().date() or end_date < start_date:
raise ValidationError('Please enter a valid end date!')
return end_date
Обновление - правильным способом очистки данных нескольких полей с возможными повышениями является (я не заметил вызов значения dict...):
def clean(self):
start_date = self.cleaned_data['start_date']
end_date = self.cleaned_data['end_date']
if start_date < timezone.now().date():
raise ValidationError('Please enter a valid start date!')
if end_date < timezone.now().date() or end_date < start_date:
raise ValidationError('Please enter a valid end date!')
return self.cleaned_data