Это не странное поведение. Django формы работают таким образом. Пожалуйста, посмотрите на исходный код здесь , чтобы понять, как работает очистка полей для django форм. Вот урезанная версия метода _clean_fields
.
def _clean_fields(self):
for name, field in self.fields.items():
# skipped
try:
# skipped
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
# skipped
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)
То, что он делает, это l oop над полями формы и для каждого поля помещает свое очищенное значение в cleaned_data
dict. Если определен метод очистки поля (clean_<FIELD_NAME>
), он вызывает этот метод для очищенных данных для этого поля и помещает его в cleaned_data
dict.
В вашем первом случае password1
следует после password
. Поскольку поля очищаются по порядку, password1
еще не очищается, когда вы пытаетесь получить к нему доступ в методе clean_password
. Это означает, что его очищенное значение еще не присутствует в cleaned_data
dict.
Во втором случае вы меняете положение password
и password1
. Теперь очистка была выполнена для password1
, и вы можете получить доступ к ее значению.
Практическое правило заключается в том, что для clean_<FIELD_NAME>
метода, вы можете получить доступ только к очищенным значениям тех полей, которые были объявлены ранее. это поле c .
Решение
Вы должны сделать это, как django в UserCreationForm . Они проверяют совпадение пароля во втором поле, т.е. пароль1 должен совпадать с паролем, а не наоборот (что по сути одинаково). Фрагмент с модификацией от здесь .
def clean_password1(self):
password = self.cleaned_data.get("password")
password1 = self.cleaned_data.get("password1")
if password and password1 and password != password1:
raise forms.ValidationError('Passwords do not match')
return password1