Форма входа в систему пишет, что «» уже существует

#python #django #authentication

Вопрос:

Итак, у меня проблема. У меня есть форма входа в систему, но когда я пытаюсь войти, она пишет, что «» уже существует. Как это возможно?Если у пользователя есть учетная запись, это означает, что она будет существовать. Но почему я совершаю эту ошибку?

views.py

 def login(request):
    if request.method == 'POST':
        form = LoginForm(request.POST, request.FILES)
        print(form.errors)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(email=cd['email'], password=cd['password'])
            if user is not None:
                if user.is_active:
                    login(request, user)
                    return HttpResponse('Authenticated successfully')
                else:
                    return HttpResponse('Disabled account')
            else:
                return HttpResponse('Invalid login')
        else:
            return HttpResponse('Form is not valid')
    else:
        form = LoginForm()
    return render(request, 'account/login.html', {'form': form})
 

Я совершаю ошибку:

<ul class="errorlist"><li>email<ul class="errorlist"><li>User with this already exists.</li></ul></li></ul>

Форма для входа в систему

 class LoginForm(ModelForm):

    class Meta:
        model = User
        fields = ['email', 'password']

        widgets = {
            'email': EmailInput(attrs={
                'class': 'form-email',
                'placeholder': 'email'
            }),
            'password': PasswordInput(attrs={
                'class': 'form-password',
                'placeholder': 'password'
            })
        }
 

Модель пользователя

 class User(models.Model):
    CHOICES = (
        ('1', 'Author'),
        ('2', 'Customer'),
        ('3', 'Author and Customer')
    )
    first_name = models.CharField(max_length=64, blank=False, verbose_name='')
    last_name = models.CharField(max_length=64, blank=False, verbose_name='')
    patronymic = models.CharField(max_length=64, blank=False, verbose_name='')
    age = models.PositiveSmallIntegerField(verbose_name='', blank=False)
    email = models.EmailField(unique=True, max_length=128, blank=False, verbose_name='')
    password = models.CharField(max_length=32, blank=False, verbose_name='')
    role = models.CharField(max_length=32, choices=CHOICES, default='Customer')
    about = models.TextField(max_length=512, verbose_name='', blank=True)
 

Ответ №1:

Когда a ModelForm не instance указан, это означает, что он используется для создания экземпляра, и, следовательно, когда is_valid вызывается в вашей форме, он обнаруживает, что указанное вами имя пользователя уже существует, и, следовательно, возвращается False . По этой причине форма, используемая для входа пользователя, должна быть обычным Form классом.

Двигаясь дальше, Django уже предоставляет встроенную форму, которую можно использовать для аутентификации django.contrib.auth.forms.AuthenticationForm [Django docs]. Глядя на вашу реализацию, у вас есть пользовательская модель пользователя с электронной почтой в качестве USERNAME_FIELD ? Он AuthenticationForm достаточно универсален, чтобы справиться с этим, поэтому вы можете напрямую использовать его в своем представлении (или, если вы хотите настроить виджеты форм, которые вы можете унаследовать от него).

Если вы хотите установить атрибуты для виджетов, просто унаследуйте AuthenticationForm их и установите в методе forms __init__ :

 from django.contrib.auth.forms import AuthenticationForm

class LoginForm(AuthenticationForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['username'].widget.attrs.update({'class': 'form-email', 'placeholder': 'email'})
        self.fields['password'].widget.attrs.update({'class': 'form-password', 'placeholder': 'password'})
 

Затем используйте эту форму в своем представлении:

 def login(request):
    if request.method == 'POST':
        form = LoginForm(request, request.POST, request.FILES)
        print(form.errors)
        if form.is_valid():
            user = form.get_user()
            if user is not None:
                if user.is_active:
                    login(request, user)
                    return HttpResponse('Authenticated successfully')
                else:
                    return HttpResponse('Disabled account')
            else:
                return HttpResponse('Invalid login')
        else:
            return HttpResponse('Form is not valid')
    else:
        form = LoginForm(request)
    return render(request, 'account/login.html', {'form': form})
 

Комментарии:

1. как я могу это сделать без встроенного класса django? Потому что я знаю, как добавить стили в форму аутентификации

2. это все еще не работает, я не хочу использовать имя пользователя, мне нужна электронная почта

3. @Ihor Только имя поля в форме username , оно будет отображаться как электронное письмо в шаблон, потому AuthenticationForm что оно закодировано таким образом, что оно будет использовать USERNAME_FIELD модель, которая установлена, AUTH_USER_MODEL чтобы найти поле и изменить это поле в отношении этого. «Это не работает» — ты даже не пробовал?

4. @Ihor Вы должны визуализировать его так, как {{ form.username }} если бы вы ранее визуализировали {{ form.email }} (я предполагаю, что это так, поскольку вы не добавили свой шаблон в вопрос)

5. о, да, извините, для меня немного необычно использовать встроенные методы. Я пробовал, и он все еще выдает мне сообщение «Форма недействительна».