一、引言
在Django项目中,默认的认证方式是通过用户名进行登录。但在实际项目中,我们往往需要提供邮箱登录的功能。本文将详细介绍如何实现这一功能,并编写一个用户注册表单,对密码和邮箱进行验证。
二、实现用户名和邮箱登录功能
首先,我们需要在views.py文件中创建一个自定义认证后端,重写authenticate方法。以下是代码实现:
from django.contrib.auth import backends
from django.contrib.auth.models import User
from django.db.models import Q
class MyBackend(backends.ModelBackend):
'''
主要实现既可以用户名登录也可以使用邮箱登录的功能
要记得在settings中配置以下字段才会生效
AUTHENTICATION_BACKENDS = (
# 这是使用自己写的
'users.views.MyBackend',
# 这是django默认使用的认证
# 'django.contrib.auth.backends.ModelBackend',)
'''
# 重写该方法
def authenticate(self, request, username=None, password=None, **kwargs):
try:
# Q 的作用是 可以通过& 和 | 连接起来 当操作符在两个Q对象之间时 会生成一个新的Q对象
# Q的详细用法可查看该地址 https://www.toutiao.com/article/6809613183938986500/
# 该表达式的意思是 如果username=username 或者 email=username
# 实现的具体效果是 无论用户使用用户名登录还是邮箱登录都可以
user = User.objects.get(Q(username=username) | Q(email=username))
# 通过check_password() 将用户的明文密码加密成哈希值
# self.user_can_authenticate(user) 判断用户是否为可用状态,如果被禁用状态,无法通过认证,建议加上
if user.check_password(password) and self.user_can_authenticate(user):
return user
except Exception as e:
return
在项目的settings.py文件中,找到AUTHENTICATION_BACKENDS配置项,将其修改为以下内容:
AUTHENTICATION_BACKENDS = (
'users.views.MyBackend',
)
这样,我们就实现了既可以用户名登录也可以使用邮箱登录的功能。
三、编写用户注册表单
接下来,我们编写一个用户注册表单,对密码和邮箱进行验证。以下是forms.py文件中的代码实现:
from django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
class RegisterForm(forms.ModelForm):
'''
用户注册时的表单
'''
email = forms.EmailField(label='用户邮箱',
min_length=3,
widget=forms.EmailInput(
attrs={'class': 'form-control',
'placeholder': '请输入邮箱:'}))
# error_messages={} 自定义错误信息 建议用默认信息就行
password1 = forms.CharField(label='确认密码',
min_length=6,
error_messages={'min_length': '密码长度不能少于6位'},
widget=forms.PasswordInput(
attrs={'class': 'form-control',
'placeholder': '请输入确认密码:'}
))
class Meta:
model = User
fields = ('username', 'email', 'password')
widgets = {
'username': forms.TextInput(
attrs={'class': 'form-control',
'placeholder': '请输入用户名:'}),
'password': forms.PasswordInput(
attrs={'class': 'form-control',
'placeholder': '请输入密码:'})
}
# 重写password1字段的钩子方法
# 自定义 局部的钩子方法 判断两次密码输入是否一致
def clean_password1(self):
# 获取通过验证的密码,判断两次输入的密码是否一致
password = self.cleaned_data.get('password')
password1 = self.cleaned_data.get('password1')
# 如果两次输入的密码不一致,抛出对应的错误
if password != password1:
raise ValidationError('两次密码输入不一致,请重新确认!')
# return 对应的字段
return password1
# 定义局部钩子方法,判断email是否已经存在
def clean_email(self):
# 获取通过验证的email
email = self.cleaned_data.get('email')
exists_email = User.objects.filter(email=email).first()
if exists_email:
raise ValidationError('已存在一位使用该邮箱的用户。')
return email