Почему проверяется, что два паролей совпадают в Django настолько сложно?
Я делаю что-то неправильно, или это серьезно то, что разработчики ожидают, что я буду писать каждый раз, когда я хочу проверить, совпадают ли два поля?
def clean(self):
data = self.cleaned_data
if "password1" in data and "password2" in data:
if data["password1"] != data["password2"]:
self._errors["password2"] = self.error_class(['Passwords do not match.'])
del data['password2']
return data
И почему мне нужно проверить, что имя пользователя уникально?
def clean_username(self):
data = self.cleaned_data['username']
if User.objects.filter(username=data).exists():
raise ValidationError('Username already taken.')
return data
Это a ModelForm
. Он должен уже знать там уникальное ограничение?
Ответы
Ответ 1
Вот что я буду делать:
Это единственный метод, который нужно определить, чтобы убедиться, что 2 пароля верны и что имя пользователя действительно.
Используйте метод clean_fieldname
, чтобы вам не нужно было делать больше работы для проверки имени пользователя.
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if not password2:
raise forms.ValidationError("You must confirm your password")
if password1 != password2:
raise forms.ValidationError("Your passwords do not match")
return password2
Вы абсолютно правы, вам dont нужно подтвердить, что имя пользователя уникально, потому что ModelForm знает, что он должен быть уникальным.
Проблема с вашим кодом заключается в том, что вы переопределяете метод clean()
, что означает, что ModelForm не выполняет свою "настоящую" чистую().
Чтобы получить подтверждение по умолчанию, вызовите super(MyForm, self).clean()
или лучше, но не переопределите clean
вообще и укажите только clean_password2
.
Ответ 2
Во-первых, вы серьезно жалуетесь на четыре строки кода котельной? Если это действительно вас беспокоит, создайте класс PasswordForm
, который содержит эту чистую логику и подстроит ее для ваших собственных форм по мере необходимости.
Во-вторых, вам не нужно вручную проверять уникальные ограничения. Как вы говорите, ModelForm делает это за вас.
Редактировать после комментария
Этот "странный синтаксис" заключается в том, что проверка того, что два поля пароля совпадают, - это другой поток, чем обычная схема вещей. Для начала вы проверяете основной clean
метод, а не специфический для поля clean_myfield
. Если бы это был последний, вы просто делаете исключение, и Django действительно удаляет данные полей.
Нет, это не 7 строк в каждой форме - см. мою заметку о подклассе - и не 7 строк раз несколько полей, потому что вы не хотите этого делать для любого другого типа поля.
Ответ 3
http://k0001.wordpress.com/2007/11/15/dual-password-field-with-django/
Изменить: выяснили, как административная форма справляется с проблемой: http://code.djangoproject.com/svn/django/trunk/django/contrib/auth/forms.py
class AdminPasswordChangeForm(forms.Form):
"""
A form used to change the password of a user in the admin interface.
"""
password1 = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
password2 = forms.CharField(label=_("Password (again)"), widget=forms.PasswordInput)
def __init__(self, user, *args, **kwargs):
self.user = user
super(AdminPasswordChangeForm, self).__init__(*args, **kwargs)
def clean_password2(self):
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if password1 and password2:
if password1 != password2:
raise forms.ValidationError(_("The two password fields didn't match."))
return password2
def save(self, commit=True):
"""
Saves the new password.
"""
self.user.set_password(self.cleaned_data["password1"])
if commit:
self.user.save()
return self.user
Ответ 4
Возможно, вы захотите добавить часть else:
для первого if
. В настоящее время функция возвращает data
без установки каких-либо ошибок, даже если один из паролей отсутствует - это предполагаемое поведение?
else:
self._errors["password"] = self.error_class(['One or both of the passwords not found'])
if "password1" in data and "password2" in data:
Это гарантирует, что оба пароля присутствуют. Без этой строки вы получите сообщение об ошибке в следующей строке, где вы читаете data[password1]
и data[password2]
, если их нет.
Следующие три строки сравнивают пароли и задают соответствующее сообщение об ошибке - это необходимо, не так ли?
Как говорится, сделайте все как можно проще, а не больше.