登录、注销和登录限制
登录
在使用authenticate
进行验证后,如果验证通过了。那么会返回一个user
对象,拿到user
对象后,可以使用django.contrib.auth.login
进行登录。
这里使用的models是继承自AbstractBaseUser
的模型
# models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
class UserManager(BaseUserManager):
def _create_user(self, phone, username, password, **kwargs):
# 这是一个受保护函数,只能被类自己中调用
# 作为create_user和create_superuser的被调用函数
if not phone:
raise ValueError("必须传递手机号码")
if not password:
raise ValueError("必须传递密码")
user = self.model(phone=phone, username=username, **kwargs) # self.model表示当前模型
user.set_password(password) # password只能这样设置
user.save()
return user
def create_user(self, phone, username, password, **kwargs):
kwargs["is_superuser"] = False # 添加is_superuser键值对
return self._create_user(phone=phone, username=username, password=password, **kwargs)
def create_superuser(self, phone, username, password, **kwargs):
kwargs["is_superuser"] = True
return self._create_user(phone=phone, username=username, password=password, **kwargs)
class InheritTwo(AbstractBaseUser, PermissionsMixin):
phone = models.CharField(max_length=11, unique=True)
username = models.CharField(max_length=20)
password = models.CharField(max_length=20)
address = models.CharField(max_length=100)
is_active = models.BooleanField(default=True)
USERNAME_FIELD = 'phone'
REQUIRED_FIELDS = []
objects = UserManager()
def get_full_name(self):
return self.username
def get_short_name(self):
return self.username
配置settings.py
中的AUTH_USER_MODEL='appname.InheritTwo'
,且为第一次数据库迁移
html编写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form action="" method="post">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
<table>
<tbody>
<tr>
<td>登陆手机号:</td>
<td><input type="text" name="phone"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>
<label for="">
<input type="checkbox" name="remember" value="1"> 记住我
</label>
</td>
<td></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="登陆"></td>
</tr>
</tbody>
</table>
</form>
</body>
</html>
登陆:
from django.shortcuts import render, redirect, reverse
from .forms import LoginForm
from django.contrib.auth import login, logout
def my_login(request):
if request.method == "GET":
return render(request, 'login.html')
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
phone = form.cleaned_data.get("phone")
password = form.cleaned_data.get("password")
remember = form.cleaned_data.get("remember")
user = authenticate(request, username=phone, password=password)
# authenticate验证
if user and user.is_active: # 如果存在且不为黑名单
# 在session表中登记信息
login(request, user)
if remember: # 是否有点"记住我"
# 设置为None,则表示使用全局的默认时间(2周)
request.session.set_expiry(None)
else:
# 浏览器结束即结束
request.session.set_expiry(0)
return HttpResponse("登陆成功")
else:
return HttpResponse("手机或密码错误")
else:
return redirect(reverse('login'))
注销
注销,或者说退出登录。通过django.contrib.auth.logout
来实现。他会清理掉这个用户的session
数据(表也会清除,类似request.session.flush()
)。
from django.contrib.auth import logout
def my_logout(request):
logout(request)
return HttpResponse("登出成功")
登录限制:使用装饰器
需要某个视图函数是需要经过登录后才能访问的。
通过django.contrib.auth.decorators.login_required
装饰器来实现。
from django.contrib.auth.decorators import login_required
@login_required(login_url='/login/') # 如果验证失败,则跳转login_url指定的页面
# 会传递 next= urls.py中视图函数对应的urls路径
# 比如当前函数的urls路径为 two/profile/ 则传递 next=/two/prifle/ <-!!!没有多一个 /
def profile(request):
return HttpResponse("登陆成功才能看见")
在/login/
的视图函数中,判断是否有这个next
查询字符串,决定是否再跳转到profile
视图函数
def my_login(request):
# ...
if user and user.is_active: # 如果存在且不为黑名单
# request.session['user_id'] = user.id
login(request, user)
if remember:
# 设置为None,则表示使用全局的默认时间(2周)
request.session.set_expiry(None)
else:
request.session.set_expiry(0)
next_url = request.GET.get('next') # 装饰器login_request修饰的函数跳转后会传递next查询字符串
if next_url:
return redirect(next_url) # 跳转回profile视图函数
else:
return HttpResponse("登陆成功")
else:
return HttpResponse("手机或密码错误")
# ...