Почему так сложно проверить, совпадают ли два пароля в Django? - PullRequest
13 голосов
/ 12 июля 2010

Я что-то не так делаю, или это серьезно , что разработчики ожидают, что я напишу каждый раз, когда я хочу проверить, совпадают ли два поля?

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

Это ModelForm.Он уже должен знать, что есть уникальное ограничение?

Ответы [ 4 ]

28 голосов
/ 17 декабря 2010

Вот что я бы сделал:

Это единственный чистый метод, который вам нужно определить, чтобы убедиться, что 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

Вы абсолютно правы, вам не нужно нужно проверять уникальность имени пользователя, потому что ModelForm знает, что оно должно быть уникальным.

Проблема с вашим кодом заключается в том, что вы переопределяете метод clean(), что означает, что ModelForm не выполняет свою «настоящую» очистку ().

Чтобы получить проверку по умолчанию, позвоните super(MyForm, self).clean() или лучше, но не переопределяйте clean и укажите только clean_password2.

4 голосов
/ 12 июля 2010

Во-первых, вы серьезно жалуетесь на четыре строки кода котельной пластины?Если это действительно вас беспокоит, создайте класс PasswordForm, содержащий эту чистую логику, и при необходимости создайте подкласс для своих собственных форм.

Во-вторых, вам не нужно проверять уникальные ограничениявручную.Как вы говорите, ModelForm сделает это за вас.

Редактировать после комментария

Этот «странный синтаксис» связан с тем, что проверка совпадения двух полей пароля отличается поток от обычной схемы вещей.Для начала вы проверяете основной clean метод, а не специфичный для поля clean_myfield.Если это было последнее, вы просто вызываете исключение, и Django действительно удаляет данные поля.

Так что нет, это не 7 строк в каждой форме - см. Мое примечание о подклассах - и это конечно - это не 7 строк по нескольким полям, потому что вы не хотите делать это для любого другого типа поля.

4 голосов
/ 17 декабря 2010

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
1 голос
/ 12 июля 2010

Возможно, вы захотите добавить 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], если ни один из них отсутствует.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...