Вход в Django с помощью электронной почты или номера телефона
Я уже очень долгое время пытаюсь найти решение проблемы в Django. Проблема заключается в том, что я пытаюсь разработать систему входа в систему, которая может использовать либо электронную почту, либо номер телефона для аутентификации пользователя.
Любая помощь будет принята с благодарностью.
Спасибо
Ну это можно сделать, создав пользовательскую модель пользователя. Это единственный известный мне способ достичь результата.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password=None):
if not email:
raise ValueError('Users must have an email address')
if not username:
raise ValueError('Users must have a username')
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
def get_profile_image_filepath(self , filepath):
return 'profile_images/' + str(self.pk) + '/profile_image.png'
def get_default_profile_image():
return "dummy_image.png"
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
profile_image = models.ImageField(max_length=255,
upload_to=get_profile_image_filepath, null=True, blank=True, default=get_default_profile_image)
hide_email = models.BooleanField(default=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.username
def get_profile_image_filename(self):
return str(self.profile_image)[str(self.profile_image).index('profile_images/' + str(self.pk) + "/"):]
# For checking permissions. to keep it simple all admin have ALL permissons
def has_perm(self, perm, obj=None):
return self.is_admin
# Does this user have permission to view this app? (ALWAYS YES FOR SIMPLICITY)
def has_module_perms(self, app_label):
return True
Это пользовательская модель пользователя, которая будет входить в систему через email пользователя .
Вы должны определить в settings.py модель auth пользователя .
В settings.py добавьте следующее
AUTH_USER_MODEL = "user_app.Account"
замените "user_app" на приложение, в чьем models.py хранится эта модель .
А также вам нужно сказать администратору, чтобы он это сделал .
перейдите в файл admin.py приложения и добавьте это .
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from account.models import Account
class AccountAdmin(UserAdmin) :
list_display = ("email" , "username" , "date_joined" , "last_login" , "is_admin" , "is_staff")
search_fields = ("email" , "username")
readonly_fields = ("id" , "date_joined" , "last_login")
filter_horizontal = ()
list_filter = ()
fieldsets = ()
admin.site.register(Account , AccountAdmin)
Другой способ достижения результата - взять у пользователя учетные данные электронной почты или номера телефона и пароль, затем в представлениях узнать имя пользователя и затем войти в систему...
Создайте форму, а затем создайте метод сохранения для этого, или сделайте это в представлениях.
Нравится :
def loginView(request) :
if request.POST :
email = request.POST.get("email")
password = request.POST.get("password")
user = User.objects.get(email = email)
if user.check_password(password) :
login(request, user)
return redirect("home")
Ну, это можно сделать, создав пользовательскую модель пользователя. Я протестировал это. Это работает.
Первые шаги
Первое, что вам нужно сделать, это создать новый проект Django. Убедитесь, что вы не запустили миграцию, потому что до этого нам еще нужно сделать несколько вещей.
После создания нового проекта Django, создайте новое приложение под названием accounts с помощью следующей команды:
python manage.py startapp accounts
Создание модели пользователя
По умолчанию модель User, предоставляемая Django, имеет поле имени пользователя и поле электронной почты. Однако нам также необходимо поле номера телефона. Чтобы добавить это поле, нам нужно расширить модель пользователя Django. В файле models.py приложения "Счета" введите следующий код:
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
Зарегистрируйте модель у администратора
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})
Написание пользовательского бэкенда
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
Обновить настройки (3 варианта)
settings.py
INSTALLED_APPS = [
...
# Third-party apps
'accounts.apps.AccountsConfig',
...
]
AUTH_USER_MODEL = 'accounts.User'
AUTHENTICATION_BACKENDS = [
'accounts.backends.EmailPhoneUsernameAuthenticationBackend'
]
Надеюсь, ваша проблема будет решена, и другие будут использовать его.