共计 9518 个字符,预计需要花费 24 分钟才能阅读完成。
一、说明
User 是 auth 模块中维护用户信息的关系模式(继承了 models.Model), 数据库中该表被命名为 auth_user
二、User 表的 SQL 描述
CREATE TABLE "auth_user" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"password" varchar(128) NOT NULL, "last_login" datetime NULL,
"is_superuser" bool NOT NULL,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL,
"email" varchar(254) NOT NULL,
"is_staff" bool NOT NULL,
"is_active" bool NOT NULL,
"date_joined" datetime NOT NULL,
"username" varchar(30) NOT NULL UNIQUE
)
导入
from django.contrib.auth.models import User
三、用户模型属性方法
-
is_staff
Boolean。决定用户是否可以访问 admin 管理界面。默认 False
-
is_active
Boolean。用户是否活跃, 默认 True。一般不删除用户,而是将用户的 is_active 设为 False
-
is_authenticated()
用户是否通过验证,登陆
request.user.is_authenticated() 可以判断当前用户是否登录
登录则为 True 否则为 False
-
make_password(password)
给密码加密 django 自带的加密功能是 hash 加盐
-
check_password(password)
检查用户输入的密码是否正确
-
set_password(password)
修改用户密码
-
authenticate() 认证用户名和密码是否正确
authenticate(username=username, password=password)
使用
from django.contrib.auth import authenticate
-
create_user() 创建用户
使用系统 User 模型
from django.contrib.auth.models import User User.objects.create_user(username, email, password)
-
request.user 获取当前登录用户对象
request.user.username 获取当前登录用户的用户名
-
last_login 自动保存 不需要自己添加代码
上一次的登录时间,为 datetime 对象,默认为当时的时间。
user.last_login
=timezone.now()
-
request.user.username
获取当前登录用户的用户名
-
login_required 设置视图函数必须登录才允许访问
from django.contrib.auth.decorators import login_required @login_required(login_url='/') # 没有登录则跳转到首页 def center(request): return Httpresponse('个人中心')
-
login 登录
-
logout 退出登录
四、注册
-
模板 register.html
<!DOCTYPE html> <html> <head> <title>注册页面</title> <style> .pg_header{position: fixed; height: 48px; top: 0; left: 0; right: 0; background-color: #2459a2; line-height: 48px; } .pg_header .logo{margin: 0 auto; float: left; width: 200px; text-align: center; line-height: 48px; font-size: 28px; color: white; } .pg_dl{left: 400px; display: inline-block; padding: 0 40px; color: white; } .pg_header .pg_dl:hover{background-color: #2459fb; cursor: pointer; } .left{margin-top: 20px; width: 400px; display: inline-block; float: left; } .pg_body{margin-top: 50px; font-size: 18px; display: inline-block; width: 200px; } .pg_body .menu{width: 800px; padding: 15px; float: left; font-weight: bold; } input[type="text"]{width: 200px; height: 25px; border-radius: 6px; } input[type="password"]{width: 200px; height: 25px; border-radius: 6px; } input[type="button"]{background-color: #555555; border: none; color: white; padding: 12px 29px; text-align: center; text-decoration: none; display: inline-block; font-size: 17px; margin: 4px 2px; cursor: pointer; border-radius: 4px; } input[type="submit"]{background-color: #555555; border: none; color: white; padding: 12px 29px; text-align: center; text-decoration: none; display: inline-block; font-size: 17px; margin: 4px 2px; cursor: pointer; border-radius: 4px; } .kong{margin-top: -54px; margin-left: 200px; float:left; padding: 15px; } .img{width: 50px; height: 40px; } .can{width: 1220px; height: 40px; line-height: 40px; margin: 0 auto; text-align: center; display: inline-block; } .tian{color: red; float: right; font-size: 12px; margin-right: -120px; margin-top: -25px; } </style> </head> <body id="i88" style="margin: 0"> <div class = "pg_header"> <a class = "logo">LOGO</a> <a class="pg_dl" id="i77">注册</a> </div> <form name="tijiao" method="post" onsubmit="return check()" action="{% url'App:register'%}"> {% csrf_token %} <div class="left"></div> <div class="pg_body"> <div class="menu">用户名:</div> <div class="kong"> <input id="text1" type="text" name="username" placeholder="请输入用户名" onblur="check()"><span id="div1" class="tian" style="margin-top: 4px">*(为必填)</span> </div> <div class="menu">密码:</div> <div class="kong"> <input id="text2" type="password" name="userpass" onblur="check()"> <span id="div2" class="tian" style="margin-top: 5px">*(为必填)</span> </div> <div class="menu">确认密码:</div> <div class="kong"> <input id="text3" type="password" name="01" onblur="check()"> <span id="div3" class="tian" style="margin-top: 5px">*(为必填)</span> </div> <div class="menu">邮箱地址:</div> <div class="kong"> <input id="text4" type="text" name="email" onblur="check()" required> <span id="div4" class="tian" style="margin-top: 5px">*(为必填)</span> </div> </div> <div class="can"> <input id="i111" type="submit" name="002" value="注 册"> <p style="width: 200px;display: inline-block;"></p> <input id="i222" type="button" name="004" value="取 消"> </div> </form> <script type="text/javascript"> // 刷新 or 取消 document.getElementById('i77').onclick = function(){location.reload(); } document.getElementById('i222').onclick = function(){location.reload(); } // 用户名验证 function checkname(){var div = document.getElementById("div1"); div.innerHTML = ""; var name1 = document.tijiao.text1.value; if (name1 == "") { div.innerHTML = "用户名不能为空!"; document.tijiao.text1.focus(); return false; } if (name1.length < 4 || name1.length > 16) { div.innerHTML = "长度 4 -16 个字符"; document.tijiao.text1.select(); return false; } var charname1 = name1.toLowerCase(); for (var i = 0; i < name1.length; i++) {var charname = charname1.charAt(i); if (!(charname >= 0 && charname <= 9) && (!(charname >= 'a' && charname <= 'z')) && (charname != '_')) { div.innerHTML = "用户名包含非法字符"; document.form1.text1.select(); return false; } } return true; } // 密码验证 function checkpassword(){var div = document.getElementById("div2"); div.innerHTML = ""; var password = document.tijiao.text2.value; if (password == "") { div.innerHTML = "密码不能为空"; {#document.tijao.text2.focus();#} return false; } if (password.length < 4 || password.length > 16) { div.innerHTML = "密码长度为 4 -16 位"; document.tijiao.text2.select(); return false; } return true; } function checkrepassword(){var div = document.getElementById("div3"); div.innerHTML = ""; var password = document.tijiao.text2.value; var repass = document.tijiao.text3.value; if (repass == "") { div.innerHTML = "密码不能为空"; document.tijiao.text3.focus(); return false; } if (password != repass) { div.innerHTML = "密码不一致"; document.tijiao.text3.select(); return false; } return true; } // 邮箱验证 function checkEmail(){var div = document.getElementById("div4"); div.innerHTML = ""; var email = document.tijiao.text4.value; var sw = email.indexOf("@", 0); var sw1 = email.indexOf(".", 0); var tt = sw1 - sw; if (email.length == 0) { div.innerHTML = "邮箱不能为空"; document.tijiao.text5.focus(); return false; } if (email.indexOf("@", 0) == -1) { div.innerHTML = "必须包含 @符号"; document.tijiao.text5.select(); return false; } if (email.indexOf(".", 0) == -1) { div.innerHTML = "必须包含. 符号"; document.tijiao.text5.select(); return false; } if (tt == 1) { div.innerHTML = "@和. 不能一起"; document.tijiao.text5.select(); return false; } if (sw > sw1) { div.innerHTML = "@符号必须在. 之前"; document.tijiao.text5.select(); return false; } else {return true;} return ture; } function check(){if (checkname() && checkpassword() && checkrepassword() && checkEmail()) {return true;} else {return false;} } </script> </body> </html>
-
views.py
from django.conf import settings # 导入配置 from django.shortcuts import render,HttpResponse,redirect,reverse from django.contrib.auth.models import User # 导入系统 User 模型 from django.contrib.auth import login,authenticate # 使用系统用户模型 以及方法 进行登录注册 退出登录等处理 def register(req): if req.method == 'POST': # 接受表单传递过来的数据 username = req.POST.get('username') userpass = req.POST.get('userpass') email = req.POST.get('email') try: # 用户的创建 User.objects.create_user(username,email,userpass) except: return HttpResponse('注册失败') return HttpResponse('注册成功') return render(req,'register.html')
五、认证用户
-
导入
from django.contrib.auth import login,authenticate
login 处理用户登录状态的方法
authenticate 认证用户的用户名和密码是否正确 正确返回用户对象 否则 None
-
视图函数
from django.conf import settings # 导入配置 from django.shortcuts import render,HttpResponse,redirect,reverse from django.contrib.auth.models import User # 导入系统 User 模型 from django.contrib.auth import login,authenticate # 用户认证 登录 def Login(req): if req.method == 'POST': username = req.POST.get('username') userpass = req.POST.get('userpass') user = authenticate(username=username,password=userpass) # 认证成功返回对象 否则 None if user: # 处理登录状态的维持 login(req,user) # 重定向到首页 return redirect(reverse('App:index')) else: return redirect(reverse('App:Login')) return render(req,'login.html')
注意:如果该用户 is_active 为 False 则认证失败
-
在模板中判断是否登录
Django 自带的用户认证授权系统
如果用户已经授权成功,说明用户已经登录成功,那么在渲染 index.html 的时候,直接展示已登录状态即可;如果用户认证失败,说明没有登录,那么在渲染 index.html 的时候,直接展示登录表单即可
{% if request.user.is_authenticated %} <h3>登录了欢迎{{request.user.username}}</h3> {% else %} <h3>没登录</h3> {% endif %}
六、修改用户密码
-
方法
set_password(new_password)
-
说明
修改密码是 User 的实例方法, 该方法不验证用户身份
user.set_password(new_password)
-
通常该方法需要和 authenticate 配合使用
user = auth.authenticate(username=username, password=old_password) if user is not None: user.set_password(new_password) user.save()
七、视图函数获取登录用户对象
# 在视图函数中获取登录用户的数据
def own(req):
# 判断是否登录
if req.user.is_authenticated:
print(req.user.username) # 获取登录的用户名
print(req.user.last_login) # 上次登录时间
return HttpResponse('在视图函数中获取登录用户的数据')
八、退出登录
logout 会移除 request 中的 user 信息, 并刷新 session
from django.contrib.auth import logout
def logout_view(request):
logout(request)
return redirect(reverse('App:index'))
九、权限判断(只允许登录用户访问)
@login_required
修饰器修饰的 view 函数会先通过 session key 检查是否登录, 已登录用户可以正常的执行操作, 未登录用户将被重定向到 login_url
指定的位置。若未指定 login_url 参数, 则重定向到settings.LOGIN_URL
# 在视图函数中获取登录用户的数据
# 当前的 own 视图函数 必须登录才能访问
# @login_required(login_url='/system_login/')
@login_required # 没有指定 login_url 则会重定向到 settings.py 中指定的 LOGIN_URL 的路由地址
def own(req):
# 判断是否登录
if req.user.is_authenticated:
print(req.user.username) # 获取登录的用户名
print(req.user.last_login) # 上次登录时间
return HttpResponse('在视图函数中获取登录用户的数据')
配置全局 就不用再每一个装饰器添加了
settings.py
LOGIN_URL =‘/login/’
十、自定义用户表
-
给 auth_user 的模型表添加新字段 iphon 和 icon 字段
-
models.py
from django.contrib.auth.models import AbstractUser class User(AbstractUser): iphone = models.CharField(max_length=11,default=15611833906) icon = models.CharField(max_length=40,default='default.jpg')
-
将用户模型设置为自己的模型
AUTH_USER_MODEL = 'App.User'
将迁移文件 和 库删除 在重新执行迁移
-
添加自定义用户认证
在 App 下新建一个 auth.py
auth.py
from django.contrib.auth.backends import ModelBackend from django.db.models import Q from App.models import User class MyBackend(ModelBackend): def authenticate(self, username=None, password=None, **kwargs): user = User.objects.filter(Q(username=username)|Q(iphone=username)|Q(email=username)).first() if user: if user.check_password(password): return user return None
注意:
当认证失败的时候返回值只能为 None 否则报错
-
在 settings.py 添加如下代码
AUTHENTICATION_BACKENDS = ('App.auth.MyBackend', )
-
视图代码更改为
from App.models import User u = User.objects.create_user(username,email,userpass,iphone='18826123687')