前戏
我们在开发项目的时候,难免要遇到用户权限的问题,例如这个用户是不是可以访问这个页面,是不是可以登录,账号是不是已经过期了等等的原因,django给我们提供了auth模块,能很方便的解决我们的这些问题。
django给我们提供了一个后台管理系统,我们先来创建一个超级用户,在项目跟目录下执行下面命令
python manage.py createsuperuser
执行成功之后,我们就在默认的auth_user表里创建了一个用户
我们可以登录到后台看看
User下的数据就是我们数据表auth_user里的数据,方便我们进行数据的更改。
authenticate
给我们提供了用户认证功能,就是验证我们的用户名和密码是不是正确的。一般需要username和password两个参数,如果认证成功,则返回一个User对象,如果认证失败,则返回None
authenticate()会在该 User 对象上设置一个属性来标识后端已经认证了该用户,且该信息在后续的登录过程中是需要的。
我们可以写一个登录函数,来判断我们输入的用户名和密码是不是正确的,我们上面已经注册了一个账号和密码
1 from django.contrib import auth 2 3 4 def login(request): 5 if request.method == 'POST': 6 username = request.POST.get('username') 7 pwd = request.POST.get('pwd') 8 obj = auth.authenticate(request, username=username, password=pwd) 9 print(obj) 10 if obj: 11 return redirect('/index/') 12 13 return render(request, 'login.html')
代码解释:
第八行我们通过authenticate进行判断用户名和密码是不是正确,里面有三个参数,第一个是request,第二个是用户名,前面的username是数据库里的字段名,后面的是用户输入的值,第三个是密码。如果验证通过,则obj是一个User对象,如果验证失败,则obj为None
login()
该函数实现一个用户登录的功能,它会在后端为该用户生成一个seeeion数据,存在django_session表里。
该函数接收一个HttpRequest对象,以及一个经过认证的User对象。
1 def login(request): 2 if request.method == 'POST': 3 username = request.POST.get('username') 4 pwd = request.POST.get('pwd') 5 obj = auth.authenticate(request, username=username, password=pwd) 6 if obj: 7 auth.login(request, obj) # obj是上面认证返回的对象 8 return redirect('/index/') 9 return render(request, 'login.html')
这样,当我们执行到第七行的时候,会自动为我们生成session。
logout()
当调用该函数时,当前请求的session信息会全部清除,该用户即使没有登录,使用该方法也不会报错,接收一个HttpRequest对象,无返回值。
我们在上面登录成功之后会进入到index页面,在index视图里写个注销的功能
def index(request): auth.logout(request) # 清除用户的session数据 return redirect('/login/')
login_requierd()
有些页面我们需要用户登录成功之后才能访问,在之前我们通过给设置cookie,获取cookie的方法来判断,django给我们提供了这样的功能,使用装饰器login_requierd()就能实现,首先需要导入
from django.contrib.auth.decorators import login_required
我们给index视图加上装饰器,在没登录的状态下访问
from django.contrib.auth.decorators import login_required @login_required # 使用装饰器添加登录校验 def index(request): return HttpResponse('index')
django报错,提示我们
Not Found: /accounts/login/
这是因为如果没有登录,django会跳转到 /accounts/login/ 这个路由,因为这个我们没有定义,所以会报错,我们把login改成 /accounts/login/ 就会跳转到登录页面了,如果不想改,就想用login。可以在settings.py里加上下面的代码
LOGIN_URL = '/login/' # 这里配置成你项目登录页面的路由
这样我们就能使用我们自定义的路由了,访问index页面,如果没有登录,跳转的路由为
http://127.0.0.1:8000/login/?next=/index/
在上面登录的视图函数里,我们登录成功后会访问固定的页面index,但是我们可能是从home页面访问的,登录之后还想回到home页面,这时我们就可以修改login视图函数了
def login(request): if request.method == 'POST': username = request.POST.get('username') pwd = request.POST.get('pwd') obj = auth.authenticate(request, username=username, password=pwd) if obj: auth.login(request, obj) # obj是上面认证返回的对象 next_page = request.GET.get('next') # django给我们提供的参数是next,所以我们通过next拿到对应的值,在通过重定向跳转到对应的页面 if next_page: return redirect(next_page) return HttpResponse('ok') return render(request, 'login.html')
is_authenticated()
用来判断当前请求是否通过了认证,通过了返回True,没通过返回False
from django.contrib.auth.decorators import login_required def login(request): if request.method == 'POST': username = request.POST.get('username') pwd = request.POST.get('pwd') obj = auth.authenticate(request, username=username, password=pwd) if obj: auth.login(request, obj) # obj是上面认证返回的对象 next_page = request.GET.get('next') # django给我们提供的参数是next if next_page: return redirect(next_page) return HttpResponse('ok') return render(request, 'login.html') @login_required # 使用装饰器添加登录校验 def index(request): print(request.user, type(request.user)) # 当前的用户对象 print(request.user.is_authenticated()) # 判断当前用户是否登录 return HttpResponse('index')
create_user()
创建新用户的方法,必须要提供username,password参数。也可以指定其他参数
要导入对应的模块
from django.contrib.auth.models import User
from django.contrib.auth.models import User def register(request): if request.method == 'POST': user = request.POST.get('username') pwd = request.POST.get('password') User.objects.create_user(username=user, password=pwd) # 创建一个用户 return redirect('/login/') return render(request, 'register.html')
指定其他参数,数据库里要有这个字段
User.objects.create_user(is_staff=1,username=user, password=pwd)
create_superuser()
创建一个超级用户,可以登录到后台
语法和上面的一样
from django.contrib.auth.models import User User.objects.create_superuser(email='',username=user, password=pwd) # 有三个参数,email在这里写死了
check_password()
auth 提供的一个检查密码是否正确的方法,需要提供当前请求用户的密码。
密码正确返回True,否则返回False。
user.check_password('密码')
set_password()
auth 提供的一个修改密码的方法,接收 要设置的新密码作为参数。
注意:要使用save()方法才能保存到数据库里面
from django.contrib.auth.models import User user.set_password(password='新密码') user.save()
自定义auth_user表
django虽然给我们提供了user表来存储用户的注册账号等信息,但不能满足我们实际项目的需求,比如我们还需要用户填地址,手机号等等信息。
我们可以通过继承内置的 AbstractUser 类,来定义一个自己的Model类。
from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): addr = models.CharField(max_length=32) phone = models.CharField(max_length=11)
注意:
按上面的方式扩展了内置的auth_user表之后,一定要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。写法如下:
# 引用Django自带的User表,继承使用时需要设置 AUTH_USER_MODEL = "app名.UserInfo"
一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了。