Django - Login with Email

Django - Login with Email

You should write a custom authentication backend. Something like this will work:

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
UserModel = get_user_model()
try:
user = UserModel.objects.get(email=username)
except UserModel.DoesNotExist:
return None
else:
if user.check_password(password):
return user
return None

Then, set that backend as your auth backend in your settings:

AUTHENTICATION_BACKENDS = ['path.to.auth.module.EmailBackend']

Updated. Inherit from ModelBackend as it implements methods like get_user() already.

See docs here: https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#writing-an-authentication-backend

Django Login with Email or Phone Number

Well, that can be done using by creating a custom user model . I have tested this. It works.

First steps

The first thing you need to do is create a new Django project. Make sure you don't run migrations because there are still a few things we need to do before then.

After creating your new Django project, create a new app called accounts with the following command:

python manage.py startapp accounts

Creating the User Model

By default, the User model provided by Django has a username field, and an email field. However, we also need a phone number field. In order to add this field, we need to extend the Django user model. In the accounts app's models.py file, type in the following code:

models.py

phone_validator = RegexValidator(r"^(\+?\d{0,4})?\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{3}\)?)\s?-?\s?(\(?\d{4}\)?)?$", "The phone number provided is invalid")

class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=100, unique=True)
phone_number = models.CharField(max_length=16, validators=[phone_validator], unique=True)
full_name = models.CharField(max_length=30)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
# is_translator = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELDS = ['email', 'full_name']

def __str__(self):
return self.email

@staticmethod
def has_perm(perm, obj=None, **kwargs):
return True

@staticmethod
def has_module_perms(app_label, **kwargs):
return True

@property
def is_staff(self):
return self.is_admin

Register the model with the admin

admin.py

class UserAdmin(BaseUserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('email', 'phone_number', 'full_name', 'is_active', 'is_admin')
list_filter = ('is_active', 'is_admin')
fieldsets = (
(None, {'fields': ('full_name', 'email', 'phone_number', 'password')}),
('Permissions', {'fields': ('is_active', 'is_admin', 'is_superuser', 'last_login', 'groups', 'user_permissions')}),
)
add_fieldsets = (
(None, {'fields': ('full_name', 'phone_number', 'email', 'password1', 'password2')}),
)
search_fields = ('email', 'full_name')
ordering = ('email',)
filter_horizontal = ('groups', 'user_permissions')

def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
is_superuser = request.user.is_superuser
if is_superuser:
form.base_fields['is_superuser'].disabled = True
return form

admin.site.register(User, UserAdmin)

forms.py

class UserLoginForm(forms.Form):
email = forms.CharField(max_length=50)
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control'}))

for login costumer in login.html

views.py

import random
from .backends import EmailPhoneUsernameAuthenticationBackend as EoP

class UserLoginView(View):
form_class = UserLoginForm
template_name = 'accounts/login.html'

def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('core:home')
return super().dispatch(request, *args, **kwargs)

def get(self, request):
form = self.form_class
return render(request, self.template_name, {'form': form})

def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = EoP.authenticate(request, username=cd['email'], password=cd['password'])
if user is not None:
login(request, user)
messages.success(request, 'You have successfully logged in!', 'success')
return redirect('core:home')
else:
messages.error(request, 'Your email or password is incorrect!', 'danger')
return render(request, self.template_name, {'form': form})

Writing a Custom Backend

backends.py

from django.contrib.auth.hashers import check_password
from django.contrib.auth import get_user_model
from django.db.models import Q

User = get_user_model()

class EmailPhoneUsernameAuthenticationBackend(object):
@staticmethod
def authenticate(request, username=None, password=None):
try:
user = User.objects.get(
Q(phone_number=username) | Q(email=username)
)

except User.DoesNotExist:
return None

if user and check_password(password, user.password):
return user

return None

@staticmethod
def get_user(user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

Update the settings (3 Options)

settings.py

INSTALLED_APPS = [
...
# Third-party apps
'accounts.apps.AccountsConfig',
...
]

AUTH_USER_MODEL = 'accounts.User'

AUTHENTICATION_BACKENDS = [
'accounts.backends.EmailPhoneUsernameAuthenticationBackend'
]

I hope your problem will be solved and others will use it.

Unable to log in with email in django

You should use a different authentication backend that checks the credentials with the given user object. Such backend can look like:

# app_name/backend.py

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

UserModel = get_user_model()

class EmailBackend(ModelBackend):

def authenticate(self, request, email=None, password=None):
try:
user = UserModel.objects.get(email=email)
except UserModel.DoesNotExist:
UserModel().set_password(password)
return None
if user is not None and user.check_password(password):
if user.is_active:
return user
return None

Then in the settings file you should use the EmailBackend for the AUTHENTICATION_BACKENDS setting [Django-doc]:

# settings.py

# ⋮
AUTHENTICATION_BACKENDS = [
'app_name.backends.EmailBackend'
]
# ⋮

Finally your Form should make use of the .create_user(…) method, or work with .set_password():

class RegisterForm(forms.ModelForm):
# ⋮

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

Python Django, How I Can use username(uname) or email as a login credentials?

You can work with a Q object to make a disjunction between email and uname:

from django.db.models import Q
if request.method=="POST":
try:
Userdetails=newacc.objects.get(
Q(email=request.POST['email']) | Q(uname=request.POST['email']),
pwd=request.POST['pwd']
)
print("Username=",Userdetails)
request.session[ 'email']=Userdetails.email
return render(request,'Logout.html')
except newacc.DoseNotExist as e:
messages.success(request,' Username / Password Invalid.')
return render(request,'Login.html')

But it seems that your user model does not make use of password hashing. I strongly advise to read the documentation on password management and hash passwords in your user model to prevent hackers from exploiting the passwords stored in the database if they manage to read that. See also this section on Customizing Authentication in Django.

Login with Email and Password in Django

Ohh!! I get it.
It's because I hed to add 'request' parameter in my authentication method.
Right code is given below

backends.py(inside 'account' named app)

class EmailBackend(object):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = User.objects.get(email=username)
except User.DoesNotExist:
return None
else:
if user.check_password(password):
return user
else:
return None

def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None

Now it is work fine!!



Related Topics



Leave a reply



Submit