Django auth
Django
中的auth
组件非常适合高效开发,它会用自带的auth_user
表来记录用户相关的数据。
并且提供了一整套服务,包括判断用户是否登录,session
限制页面访问,创建用户,注销用户等等。
通过以下代码即可导入auth
组件。
from django.contrib import auth
使用auth
组件前,一定要切记生成物理表。
python manage.py migrate
此外,注意一点:
auth
表中的数据和admin
后台管理是相通的。
我们可以看一下这张表中的字段信息。
id 主键
username 用户名
password 密码(sha256加密)
last_login 上次登录时间
is_superuser 是否是管理员
first_name 姓
last_name 名
email 邮箱地址
is_staff 是否是工作人员
is_activ 是否激活
date_joined 加入日期
登录相关
authenticate
验证用户名及密码是否正确,最少两个参数,即username
和password
。
返回值是一条记录对象,并且该对象上会设置一个属性来标识该用户已经通过认证。
user_obj = auth.authenticate(request,username=username,password=password) # request选填
login
该方法能够将authenticate()
返回的用户对象存入至request
对象中,通过request.user
即可调用出当前对象。
并且该方法还会自动生成一个session
保存至session
表中。
只要使用
login(request,user_obj)
之后,request.user
就能拿到当前登录的用户对象。否则
request.user
得到的是一个匿名用户对象(AnonymousUser Object
)。
class Login(View):
def get(self,request):
return render(request,"login.html")
def post(self,request):
username = request.POST.get("username")
password = request.POST.get("password")
user_obj = auth.authenticate(
username=username,password=password) # 拿到用户记录对象
if user_obj:
auth.login(request,user_obj) # 封装对象至request中,并且添加session
return redirect("/index/")
else:
return redirect("/register/") # 跳转到注册页面
logout
该方法接受一个HttpRequest
对象,无返回值。
当调用该函数时,当前请求的session
信息会全部清除。该用户即使没有登录,使用该函数也不会报错。
class logout(View):
def get(self,request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
is_authenticated
{% if request.user.is_authenticated %} <!-- 前端不需要加括号 -->
<a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密码</a>
{% endif %}
login_requierd
auth
组件给我们提供的一个装饰器工具,用来快捷的给某个视图添加登录校验。
需要先导入该装饰器:
from django.contrib.auth.decorators import login_required
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class logout(View):
def get(self,request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
LOGIN_URL = '/login/' # 这里配置成你项目登录页面的路由
注册相关
create_user
创建一个普通用户。需要提供必要参数(username、password)等
注意:我们要先导入auth_user
表才行,此外,所有创建用户等密码都是密文。
from django.contrib.auth.models import User
class Register(View):
def get(self,"register.html")
def post(self,request):
username = request.POST.get("username")
password = request.POST.get("password")
repeat_password = request.POST.get("repeat-password")
if repeat_password == password:
if User.objects.filter(username="username").exists(): # 如果表中不存在该数据时
User.objects.create_user(
username = username,password = password,)
return redirect("/index/")
else:
return HttpResponse("用户已存在")
else:
return HttpResponse("密码不一致,请重新输入")
create_superuser
创建一个超级用户。需要提供必要参数(username、password、email)等
注意:创建超级用户一般会使用命令行创建,不要使用代码进行创建。
from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
修改密码
check_password
需要一个参数,即老密码。判断老密码是否输入正确
set_password
设置密码,接收要设置的新密码作为参数。
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class edit_password(View):
def get(self,"edit_password.html",locals())
def post(self,request):
username = request.POST.get("username")
old_password = request.POST.get("old_password")
new_password = request.POST.get("new_password")
user_obj = request.user
if user_obj.check_password(old_password): # 验证老密码是否正确
user_obj.set_password(new_password) # 设置密码
user_obj.save()
auth.login(request,user_obj) # 重新封装对象至request中,并且添加session
return redirect("/index/")
else:
return HttpResponse("密码错误")
其他属性
属性 | 描述 |
---|---|
user_obj.is_staff | 用户是否拥有网站的管理权限. |
user_obj.active | 是否允许用户登录,设置为 False,可以在不删除用户的前提下禁止用户登录。 |
扩展auth_user
我们可以通过继承内置的 AbstractUser
类,来定义一个自己的Model
类。
这样就可以扩展auth_user
表中的字段了。
注意:这必须是在没执行
python manage.py migrate
之前
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
"""
用户信息表
"""
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11,null=True,unique=True)
def __str__(self):
return self.username
按上面的方式扩展了内置的auth_user
表之后,一定要在settings.py
中告诉Django
,我现在使用我新定义的UserInfo
表来做用户认证。写法如下:
# 引用Django自带的User表,继承使用时需要设置
AUTH_USER_MODEL = "app名.UserInfo(表名)"
自定义认证系统默认使用的数据表之后,我们就可以像使用默认的auth_user
表那样使用我们的UserInfo
表了
创建普通用户:
UserInfo.objects.create_user(username='用户名',password='密码')
创建超级用户:
UserInfo.objects.create_superuser(username='用户名',password='密码')
一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的
auth_user
表了。
全套代码
最终效果
路由层
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/',admin.site.urls),url(r'^index/',views.Index.as_view(),name='index'),url(r'^login/',views.Login.as_view(),name='login'),url(r'^logout/',views.logout.as_view(),name='logout'),url(r'^register/',views.Register.as_view(),name='register'),url(r'^edit_password/',views.edit_password.as_view(),name='edit_password'),url(r'^other/',views.Other.as_view(),name='other'),]
视图函数
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
# Create your views here.
class Index(View):
def get(self,"index.html",locals())
class Login(View):
def get(self,user_obj) # 封装对象至request中,并且添加session
return redirect("/index/")
else:
return redirect("/register/") # 跳转到注册页面
@method_decorator(login_required(login_url='/login/'),request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
class Register(View):
def get(self,request):
username = request.POST.get("username")
password = request.POST.get("password")
repeat_password = request.POST.get("repeat-password")
if repeat_password == password:
if not User.objects.filter(username=username): # 如果表中不存在该数据时
User.objects.create_user(
username = username,)
return redirect("/index/")
else:
return HttpResponse("用户已存在")
else:
return HttpResponse("密码不一致,请重新输入")
@method_decorator(login_required(login_url='/login/'),user_obj) # 重新封装对象至request中,并且添加session
return redirect("/index/")
else:
return HttpResponse("密码错误")
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Other(View):
def get(self,request):
if not request.user.is_authenticated():
return redirect("/login/")
else:
return HttpResponse("欢迎来到其他页面")
模板层
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8">
<Meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Document</title>
<link href='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<h1>欢迎来到主页</h1>
<a class="btn btn-primary" href="{% url 'login' %}" role="button">登录</a>
<a class="btn btn-warning" href="{% url 'register' %}" role="button">注册</a>
{% if request.user.is_authenticated %}
<a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密码</a>
<a class="btn btn-danger" href="{% url 'logout' %}" role="button">注销</a>
{% endif %}
</body>
</html>
edit_password.html
<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8">
<Meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Document</title>
<link href='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>修改密码</legend>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用户名" value="{{request.user.username}}" readonly>
</div>
<div class="form-group">
<label for="old_password">旧密码</label>
<input type="password" class="form-control" id="old_password" name="old_password" placeholder="密码">
</div>
<div class="form-group">
<label for="new_password">新密码</label>
<input type="password" class="form-control" id="new_password" name="new_password" placeholder="密码">
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8">
<Meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Document</title>
<link href='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>登录用户</legend>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="text" class="form-control" id="password" name="password" placeholder="密码">
</div>
<button type="submit" class="btn btn-primary">登录</button>
</form>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8">
<Meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Document</title>
<link href='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>注册用户</legend>
<div class="form-group">
<label for="username">用户名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用户名">
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="text" class="form-control" id="password" name="password" placeholder="密码">
</div>
<div class="form-group">
<label for="repeat-password">确认</label>
<input type="text" class="form-control" id="repeat-password" name="repeat-password" placeholder="重复输入密码">
</div>
<button type="submit" class="btn btn-primary">注册</button>
</form>
</body>
</html>