Подтвердить что ты не робот

Почему проверяется, что два паролей совпадают в 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. Он должен уже знать там уникальное ограничение?

4b9b3361

Ответ 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], если их нет.

Следующие три строки сравнивают пароли и задают соответствующее сообщение об ошибке - это необходимо, не так ли?

Как говорится, сделайте все как можно проще, а не больше.