Пользовательская проверка электронной почты в форме django

В моем django Account app у меня есть модель для Account

class Account(AbstractBaseUser):

    wallet_value = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    username = models.CharField(max_length=100)
    email = models.EmailField(max_length=200, unique=True)
    phone_number = models.CharField(max_length=20)

    """SOME OTHER REQUIED FIELD"""
    date_joined = models.DateTimeField(auto_now_add=True)
    last_login = models.DateTimeField(auto_now_add=True)
    is_admin = models.BooleanField(default=False)
    
    is_staff = models.BooleanField(default=False)
    is_superadmin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=False)

    USERNAME_FIELD = "email"

    REQUIRED_FIELDS = ["first_name", "last_name", "username"]

У меня также есть форма регистрации, которая отвечает за функцию регистрации

class RegistrationForm(forms.ModelForm):
    password = forms.CharField(
        widget=forms.PasswordInput(
            attrs={
                "class": "form-control",
            }
        )
    )

    confirm_password = forms.CharField(
        widget=forms.PasswordInput(attrs={"class": "form-control"})
    )
    first_name = forms.CharField(
        widget=forms.TextInput(
            attrs={
                "placeholder": "Enter First Name",
                "class": "form-control",
            }
        )
    )

    last_name = forms.CharField(
        widget=forms.TextInput(
            attrs={"placeholder": "Enter Last Name", "class": "form-control"}
        )
    )
    email = forms.CharField(
        widget=forms.EmailInput(
            attrs={
                "placeholder": "Enter Email Adress",
                "class": "form-control",
            }
        )
    )

    phone_number = forms.CharField(
        widget=forms.NumberInput(
            attrs={"placeholder": "Enter Phone Number", "class": "form-control"}
        )
    )

    class Meta:
        model = Account
        fields = [
            "first_name",
            "last_name",
            "email",
            "phone_number",
            "password",
            "confirm_password",
        ]

    def __init__(self, *args, **kwargs):
        super(RegistrationForm, self).__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = super(RegistrationForm, self).clean() 
        password = cleaned_data.get("password")
        confirm_password = cleaned_data.get("confirm_password")
        if password != confirm_password:
            raise forms.ValidationError(
                "password dose not match",
            )

и в моем views.py, который будет обрабатывать регистрациюو Я использую валидацию формы, так что если она действительна, я получу поля и создам пользователя

if form.is_valid():
    # get the fields
    # create the user in database

Теперь у меня есть сценарий, в котором пользователь вводит свои данные в регистрационной форме и ссылка активации будет отправлена на его электронную почту, так что как только он или она нажмет на ссылку активации, его или ее учетная запись будет активирована. Поэтому каждый раз, когда в форму регистрации вводится email, я должен проверять, есть ли этот email в базе данных или нет. Если его нет в базе данных, создайте пользователя и отправьте ссылку активации на этот email, но если он есть в базе данных, мы должны знать, активирован ли этот email или нет. Если да, мы выдадим ошибку, что этот email существует в базе данных, поэтому войдите, но если нет, мы должны проверить, истек срок действия предыдущей ссылки активации или нет. . если да, то отправляем еще одну ссылку активации и сообщаем об этом пользователю, а если нет, то просто сообщаем пользователю, что на его почту была отправлена ссылка активации и он должен ее активировать. алгоритм примерно такой

# user click on registration button after fill the fields
if emailIsInDatabase:
    if isAcitve:
        raise forms.ValidationError("there is an account with this email. please signin")
    else:
        if activationLinkIsExpired:
            # send another activation link
            # inform the user about that
        else:
            # inform the user to activate his or her link
else:
    # send the activation link to the email

Теперь проблема в следующем.Представьте себе сценарий, что пользователь регистрируется на сайте с неправильным email (то есть для другого человека), поэтому после нажатия кнопки submit, он или она понимает, что email неправильный и регистрируется с правильным email. Теперь, если другой пользователь, для которого был отправлен первый email, захочет создать аккаунт), когда он или она нажмет на кнопку sumbit, используя этот email, потому что этот email находится в базе данных и еще не активирован, будет вызвана проверка формы на уникальное значение email, и она выдаст ошибку, что уже есть аккаунт с этим email, поэтому она не попадет внутрь условия form.is_valid(), и мы не сможем узнать, что нам нужно проверить наличие ссылки активации.

Я уже пытался найти специальную проверку электронной почты в форме и просто закончил на этой части в чистой функции в форме : cleaned_data = super(RegistrationForm, self).clean()

и как только я удалил эту часть и просто использовал чистые данные от себя вот так cleaned_data = self.cleaned_data Он не проверял уникальность электронной почты, но я думаю, что это не лучший способ, потому что, делая это, я просто удаляю все другие проверки, которые форма сделала для других параметров, поэтому я ищу способ просто удалить валидацию уникальности электронной почты. Я также использовал функцию clean_eamil для конкретной валидации электронной почты, но это не помогло, потому что после этого будет вызвана функция clean, и моя собственная валидация будет бесполезной. Так какое решение здесь есть? Спасибо

Используйте EmailField [Django-doc]:

class RegistrationForm(forms.ModelForm):
    # …
    email = forms.EmailField(
        widget=forms.EmailInput(
            attrs={
                'placeholder': 'Enter Email Adress',
                'class': 'form-control',
            }
        )
    )

Это выполнит проверку, даже для сфабрикованного POST-запроса, который таким образом обойдет проверку HTML.

Вернуться на верх