BlackTrub
@BlackTrub
Костыль developer

Django Unique email?

Здравствуйте. Имею следующую forms.py:
class RegisterForm(ModelForm):
    error_messages = {
        'password_mismatch': "Пароли не совпадают",
        'invalid': "Пользователь с таким e-mail уже существует",
    }
    password1 = forms.CharField(
        label="Пароль",
        strip=False,
        widget=forms.PasswordInput,
        )
    password2 = forms.CharField(
        label="Повторите пароль",
        strip=False,
        widget=forms.PasswordInput,
        help_text="Введите одинаковые пароли"
        )

    class Meta:
        model = User
        fields = ("username", "email",)

    def unique_email(self):
        email = self.cleaned_data["email"]
        if User.objects.filter(email=email).count() > 0 and email:
            raise forms.ValidationError(
                self.error_messages['invalid'],
                code='invalid',
                )
        return email

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(
                self.error_messages['password_mismatch'],
                code='password_mismatch',
            )
        self.instance.username = self.cleaned_data.get('username')
        password_validation.validate_password(self.cleaned_data.get('password2'), self.instance)
        return password2

    def save(self, commit=True):
        user = super(RegisterForm, self).save(commit=False)
        user.email = self.cleaned_data["email"]
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

А так же к ней views.py:
class RegisterView(FormView):
    template_name = 'blog/reg.html'
    form_class = RegisterForm
    success_url = '/login'

    def form_valid(self, form):
        form.unique_email()
        form.clean_password2()
        form.save()
        return super(RegisterView, self).form_valid(form)

Все прекрасно функционирует, но задумался о уникальности email адреса, написал метод, он тоже работает, проблема с forms.ValidationError - при введении не уникального email он выдаёт:
ValidationError at /reg/
['Пользователь с таким e-mail уже существует']
Request Method: POST
Request URL: 127.0.0.1:8000/reg
Django Version: 1.9.5
Exception Type: ValidationError
Exception Value:
['Пользователь с таким e-mail уже существует']

Что тоже логично, но я хочу что бы он возвращал меня на страницу с регистрацией и уже там мне писал что мой email не уникален. Подскажите в какую сторону копать?
p.s. Многие фрагменты брал из исходников django, а если быть точным UserCreationForm, вот с их методом по проверке второго пароля всё прекрасно работает и возвращает на страницу регистрации с ошибкой.
  • Вопрос задан
  • 1061 просмотр
Решения вопроса 1
@deliro
1. Уникальность лучше ставить на уровне БД. Переопределить юзера, в Meta-классе дописать unique_together = [['email']]
2. Если первый пункт по каким-то причинам отметается, метод unique_email замени на clean_email и FormView будет сам вызывать его. К тому же, эксепшены из unique_email ты никак не отлавливаешь, вот он и вываливает ошибку.
3. if User.objects.filter(email=email).count() > 0 and email: - это неэффективно. В первую очередь, нужно проверять на то, что email не пуст, а потом уже на то, что он присутствует в БД (меньше запросов). К тому же, count вызывать для этого затратно. Лучше сделать так:
if email and User.objects.filter(email=email).exists():
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы