这个东西是用来判断用户是否存在所用的函数,一般来说,我们是这样导入的:
from django.contrib.auth import login, authenticate, logout
但是,当我们看源码的时候,我们就能发现,他在这个里面又调用了authenticate,这个authenticate从哪来?位置就是下边图片所示。
代码如下:
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
if username is None or password is None:
return
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
这个代码是class ModelBackend(BaseBackend):里面的一个函数,所以,真正实现验证逻辑的是这个类里面的authenticate,再看这个函数,大概也能看出来,是根据username和password来判断这个用户是否存在的,所以我们也能明白为什么在用authenticate函数的时候必须传入这两个参数了。人家底层就是根据这两个查找的,肯定要这样传入,但是,问题来了,如果我们想要用电话登录呢,这个很明显就不行了。怎么办呢,能不能对这个进行重写代码的操作呢,什么办法能重写类里面这个方法呢,我是不是可以继承这个类,然后对这个方法进行重写,这很显然是个最理想的办法,我们可以仿照这个办法,对这个方法进行重写。代码如下:
from django.contrib.auth.backends import ModelBackend, UserModel
from . import models
class UsernameMobileBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try:
user = models.User.objects.get(username=username)
user.check_password(password=password)
return user
except UserModel.DoesNotExist:
try:
user = models.User.objects.get(mobile=username)
user.check_password(password=password)
return user
except UserModel.DoesNotExist:
return None
我写了这样的代码,继承了这个类,并且将里面的这个函数写成了我希望的样子,但是问题又来了,怎样才能让系统执行到authenticate函数时,找到的是咱写的类里面的authenticate而不是系统自带ModelBackend里面的authenticate方法呢??
其实系统已经给过提示了,就在开头:
类的开头都已经写了,需要到这个里面就行配置,配置完就能找到我们的了。需要到settings里面把定义好的常量进行修改了,修改成我们想要的就行。这种配置文件一般都在conf里面,常量的定义一般是在
我们找到了这个常量:
我们看到了熟悉的东西:ModelBackend,这不就是我们想要的东西吗,我们把他进行修改,django在执行的时候就能找到我们写的类了。
他是这样写的,我们可以去自己的配置文件对他进行修改(不建议在源文件就行修改)。
这是个包路径,根据导包路径,我们就可以找到我们自己写的继承自ModelBackend的类了。这样下次我们在用authenticate的时候找的就是自己写的类里面的authenticate了。
整体来说,是根据源码一步一步仿照来的,不太难,很容易理解。