[Python] Unable to authenticate Django user with email instead of username

Discussão em 'Python' iniciado por Stack, Março 21, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to implement email-based authentication in Django instead of using the default username. I’ve updated my User model and authentication backend, but I’m still unable to authenticate users with their email addresses.

    views.py

    from django.shortcuts import render,HttpResponseRedirect
    from .forms import UserLoginForm,UserSignUpForm
    from django.contrib.auth import authenticate,login,logout,get_user
    from django.contrib import messages
    from .models import UserRegister
    # Create your views here.

    def home(request):
    return render(request,'home.html')

    def form(request):
    if request.method=="POST":
    if 'login' in request.POST:
    login_form = UserLoginForm(request,data=request.POST)
    signup_form =UserSignUpForm()
    if login_form.is_valid():
    email = login_form.cleaned_data.get('email')
    password = login_form.cleaned_data.get('password')
    user = authenticate(request,email=email,password=password)
    if user is not None:
    login(request,user)
    messages.success(request, "Successfully logged in!")
    return HttpResponseRedirect('/home')

    else:
    print("Authentication Failed")
    messages.error(request,"Invalid email or password")
    login_form.add_error(None,"Invalid email or password")
    else:
    messages.error(request,"Please fix the errors below.")
    print("Login form error:",login_form.errors)
    print("Non-field errors:", login_form.non_field_errors())
    for field in login_form:
    print(f"Field Error: {field.name} - {field.errors}")
    print(request.POST)

    if 'signup' in request.POST:
    login_form = UserLoginForm()
    signup_form =UserSignUpForm(request.POST)
    if signup_form.is_valid():
    form_info = UserRegister(
    username=signup_form.cleaned_data.get('username'),
    email=signup_form.cleaned_data.get('email'),
    password=signup_form.cleaned_data.get('password1')
    )
    form_info.save()
    messages.success(request, "Successfully signup!")
    return HttpResponseRedirect('/home')

    else:
    messages.error(request,"Please fix the errors below.")
    print("Login form error:",signup_form.errors)
    print("Non-field errors:", signup_form.non_field_errors())
    for field in signup_form:
    print(f"Field Error: {field.name} - {field.errors}")
    else:
    login_form = UserLoginForm()
    signup_form=UserSignUpForm()

    return render(request,'form.html',{'login_form':login_form,'signup_form':signup_form})


    form.py

    from django import forms
    from django.contrib.auth.forms import UserCreationForm,AuthenticationForm
    from .models import UserRegister
    from django.contrib.auth import authenticate
    class UserSignUpForm(UserCreationForm):
    username = forms.CharField(max_length=50,required=True,widget=forms.TextInput(attrs={'id':'signup-username'}))
    email = forms.EmailField(max_length=70,required=True,widget=forms.TextInput(attrs={'id':'signup-email'}))
    password1 = forms.CharField(max_length=128,required=True,widget=forms.PasswordInput(attrs={'id':'signup-password1'}))
    password2 = forms.CharField(max_length=128,required=True,widget=forms.PasswordInput(attrs={'id':'signup-password2'}))

    class Meta:
    model = UserRegister
    fields = ['username','email','password1','password2']

    class UserLoginForm(AuthenticationForm):
    email = forms.EmailField(max_length=70, required=True, widget=forms.TextInput(attrs={'id': 'login-email'}))
    password = forms.CharField(max_length=128, required=True, widget=forms.PasswordInput(attrs={'id': 'login-password'}))

    def clean(self):
    email = self.cleaned_data.get('email')
    password = self.cleaned_data.get('password')

    if email and password:
    self.user_cache = authenticate(request=self.request, email=email, password=password)
    if self.user_cache is None:
    raise forms.ValidationError("Invalid email or password")
    return self.cleaned_data


    models.py

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    from django.utils import timezone

    from django.contrib.auth.hashers import make_password


    class UserRegister(AbstractUser):
    username = models.CharField(max_length=50,unique=True,db_index=True)
    email = models.EmailField(unique=True)
    password = models.CharField(max_length=128)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(default=timezone.now)


    groups = models.ManyToManyField(
    'auth.Group',
    related_name='custom_user_groups',
    blank=True,
    help_text='The groups this user belongs to.'
    )
    user_permissions = models.ManyToManyField(
    'auth.Permission',
    related_name='custom_user_permissions',
    blank=True,
    help_text='Specific permissions for this user.'
    )

    class Meta:
    verbose_name = "Custom User "
    verbose_name_plural = "Custom Users "

    def __str__(self):
    return self.username



    backends.py

    from django.contrib.auth.backends import ModelBackend
    from .models import UserRegister

    class CustomAuthBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
    try:
    user = UserRegister.objects.get(username=username)
    if user.check_password(password):
    return user
    except UserRegister.DoesNotExist:
    print('Unable to authenticate')
    return None
    def get_user(self, user_id):
    try:
    return UserRegister.objects.get(pk=user_id)
    except UserRegister.DoesNotExist:
    return None


    form.html

    {% extends "base.html" %}
    {% block title %}
    Form
    {% endblock %}

    {% load static %}

    {% block css_files %}
    <link rel="stylesheet" href="{% static 'tracker/form.css' %}">
    {% endblock %}
    {% block content %}
    <section class="forms-section">
    <h1 class="section-title">Login & Signup Forms</h1>
    <div class="forms">
    <div class="form-wrapper is-active">
    <button type="button" class="switcher switcher-login">
    Login
    <span class="underline"></span>
    </button>
    <form class="form form-login" method="post" action="{% url 'form' %}">
    {% csrf_token %}
    <fieldset>
    <legend>Please, enter your email and password for login.</legend>
    <div class="input-block">
    <label for="login-email">E-mail</label>
    {{ login_form.email }}
    {% if login_form.email.errors %}
    <div class="error-message">
    {% for error in login_form.email.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    <div class="input-block">
    <label for="login-password">Password</label>
    {{ login_form.password }}
    {% if login_form.password.errors %}
    <div class="error-message">
    {% for error in login_form.password.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    </fieldset>
    <button type="submit" class="btn-login" name="login">Login</button>
    </form>
    </div>
    <div class="form-wrapper">
    <button type="button" class="switcher switcher-signup">
    Sign Up
    <span class="underline"></span>
    </button>
    <form class="form form-signup" method="post" action="{% url 'form' %}">
    {% csrf_token %}
    <fieldset>
    <legend>Please, enter your email, password and password confirmation for sign up.</legend>
    <div class="input-block">
    <label for="signup-username">Username</label>
    {{ signup_form.username }}
    {% if signup_form.username.errors %}
    <div class="error-message">
    {% for error in signup_form.username.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    <div class="input-block">
    <label for="signup-email">E-mail</label>
    {{ signup_form.email }}
    {% if signup_form.email.errors %}
    <div class="error-message">
    {% for error in signup_form.email.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    <div class="input-block">
    <label for="signup-password1">Password</label>
    {{ signup_form.password1 }}
    {% if signup_form.password1.errors %}
    <div class="error-message">
    {% for error in signup_form.password1.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    <div class="input-block">
    <label for="signup-password2">Confirm Password</label>
    {{ signup_form.password2 }}
    {% if signup_form.password2.errors %}
    <div class="error-message">
    {% for error in signup_form.password2.errors %}
    <p>{{ error }}</p>
    {% endfor %}
    </div>
    {% endif %}
    </div>
    </fieldset>
    <button type="submit" class="btn-signup" name="signup">Sign Up</button>
    </form>
    </div>
    </div>
    </section>
    <script src="{% static 'tracker/form.js' %}"></script>
    {% endblock %}


    error:-

    Unable to authenticate
    Login form error: <ul class="errorlist"><li>username<ul class="errorlist"><li>This field is required.</li></ul></li><li>__all__<ul class="errorlist nonfield"><li>Invalid email or password</li></ul></li></ul>
    Non-field errors: <ul class="errorlist nonfield"><li>Invalid email or password</li></ul>
    Field Error: username - <ul class="errorlist"><li>This field is required.</li></ul>
    Field Error: password -
    Field Error: email -
    <QueryDict: {'csrfmiddlewaretoken': ['N9kPmMtMtS54Te0Ln8icxMb3UBLmhilagTu5eEPGDKr8irXGOg7qCTFdsbNozh4z'], 'email': ['jain22hardik@gmail.com'], 'password': ['hj@123456'], 'login': ['']}>
    [22/Mar/2025 00:20:55] "POST /form/ HTTP/1.1" 200 4855


    Here’s what I’ve tried so far:

    Updated AUTH_USER_MODEL to a custom User model with EMAIL_FIELD set to email.

    Customized the login form to replace username with email and included a password field.

    Implemented a custom authentication backend to authenticate users using their email addresses.

    Despite these changes, the login form still expects a username field and fails with the "Invalid email or password" error. How can I resolve this and fully transition to email-based authentication in Django?

    Any guidance or advice would be greatly appreciated. Let me know if additional details or code snippets would help

    Continue reading...

Compartilhe esta Página