django的表单验证只能实现用户输入username登录,那么如何实现用户输入手机号、昵称 和 用户名都可以登录呢?
实现方法:在表单验证的基础上,重写authenticate方法,实现多种字段登录
代码例子:
原来代码的表单登录方法如下:
class StaticLoginView(View):
def post(self, request, *args, **kwargs):
# 1.初步验证:为防止脚本攻击,无论前端验证与否 后端都要验证!使用表单验证!
static_login_form = StaticLoginForm(request.POST) # 实例化表单
if static_login_form.is_valid():
# 2.查数据库,通过用户名和密码校验用户是否存在,返回user对象
username = static_login_form.cleaned_data["username"]
password = static_login_form.cleaned_data["password"]
user = authenticate(username=username, password=password)
if user:
login(request, user) # login封装了登录的细节(将session_key保存到cookie中)
# 登录成功后返回原来的页面
next = request.GET.get("next", "")
if next:
return HttpResponseRedirect(next)
else:
return HttpResponseRedirect(reverse("index")) # 登录成功之后跳转到首页
else:
return render(request, "login.html",
{"msg": "用户名或密码错误", "static_login_form": static_login_form})
else:
return render(request, "login.html",
{"static_login_form": static_login_form})
注意这里的authenticate方法默认使用的是 ...\django\contrib\auth\backends.py中的方法,只能取到username
class ModelBackend: """ Authenticates against settings.AUTH_USER_MODEL. """ def authenticate(self, request, username=None, password=None, **kwargs): if username is None: username = kwargs.get(UserModel.USERNAME_FIELD) try: user = UserModel._default_manager.get_by_natural_key(username) except UserModel.DoesNotExist: # Run the default password hasher once to reduce the timing # difference between an existing and a nonexistent user (#20760). UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): return user
为了增加用户输入的多样性:昵称、手机号等
可以重写authenticate方法:
在表单登录的视图函数前加上:
from django.contrib.auth.backends import ModelBackend from django.db.models import Q
class CustomAuth(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username=username) | Q(mobile=username) | Q(nick_name=username)) # 输入username和mobile都能查询到用户
if user.check_password(password): # 校验密码
return user
except Exception as e:
return None
在django工程的settings.py中配置:
AUTHENTICATION_BACKENDS = [ "apps.users.views.CustomAuth" ]
即可生效