Django登录与电子邮件或电话号码



很长一段时间以来,我一直在试图找到Django问题的解决方案。问题是我正在尝试开发一个登录系统,而不是使用电子邮件或电话号码来验证用户。

这可以通过创建自定义用户模型来实现。我对此进行了测试。它的工作原理。

的第一步你需要做的第一件事是创建一个新的Django项目。请确保您没有运行迁移,因为在此之前我们还有一些事情需要做。

创建新的Django项目后,用下面的命令创建一个名为accounts的新应用:

python manage.py startapp accounts

创建用户模型

默认情况下,Django提供的User模型有一个username字段和一个email字段。但是,我们还需要一个电话号码字段。为了添加这个字段,我们需要扩展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注册模型

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'}))

用于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 Options)

settings.py

INSTALLED_APPS = [
...
# Third-party apps
'accounts.apps.AccountsConfig',
...
]
AUTH_USER_MODEL = 'accounts.User'
AUTHENTICATION_BACKENDS = [
'accounts.backends.EmailPhoneUsernameAuthenticationBackend'
]

我希望你的问题将得到解决,其他人将使用它。

这可以通过创建自定义用户模型来实现。这是我所知道的达到这个结果的唯一方法。

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

这是自定义用户模型,它将通过用户的电子邮件登录。

您必须在settings.py中定义用户授权模型。

在settings.py中添加

AUTH_USER_MODEL = "user_app.Account"

替换"user_app"在model .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")

相关内容

最新更新