一. 登陆
# 1. 需要依赖中间件
# 2. 需要依赖工具类-code.py
# 3. 需要依赖工具类-bootstrap.py
# 4. 需要依赖工具类-md5_data.py
# 5. 将APP中的views.py删除, 创建 views文件夹-->login.py
二. 前置:session和cookie
登陆成功后获取:
cookie随机字符串
session用户信息
# 在其他需要登陆才能访问的页面中,都需要加入验证
# 检查用户是否已登陆,已登陆可以继续向下走,未登录,跳转登陆页面
# 用户发来请求,获取cookie随机字符串,拿着随机字符串查看session中有没有
# request.session["info"] # 不存在会报错
目标: 在所有的视图函数前面统一加上判断(太麻烦,使用中间件解决)
info = request.session.get("info")
if not info:
return redirect("/login/")
可以直接在模板中使用设置的session
request.session["info"] = {"id": admin_object.id, "name": admin_object.username} # 会自动生成cookie和在服务器生成session
request.session.set_expiry(60 * 60 * 24 * 7) # 设置session时长-7天免登录
{{ request.session.info.name }}
三. APP-models.py创建管理员表
from django.db import models
class Admin(models.Model):
"""管理员表"""
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
# 关联的字段是一个对象,需要加上__str__返回字段
def __str__(self):
return self.username
# 执行
python manage.py makemigrations
python manage.py migrate
四. 编写url
from bbc_list.views import login
urlpatterns = [
path('login/', login.login), # 登录页的url
path("image/code/", login.image_code), # 图片验证码的url
]
五. 编写视图函数(APP-->views-->login.py)
from django import forms
from django.http import HttpResponse
from django.shortcuts import render, redirect
# 使用Form组件
from bbc_list import models
from bbc_list.utils.bootstrap import BootStrapForm
from bbc_list.utils.md5_data import md5
from bbc_list.utils.code import check_code
class LoginForm(BootStrapForm):
# form需要自定义字段
username = forms.CharField(
label="用户名",
widget=forms.TextInput,
required=True # required=True: 必填
)
password = forms.CharField(label="密码",
widget=forms.PasswordInput(render_value=True), # render_value=True:在输入框保留用户输入的内容
required=True)
code = forms.CharField(label="验证码",
widget=forms.TextInput,
required=True)
# 定义一个钩子方法获取密码
def clean_password(self):
# # cleaned_data获取用户输入的内容: {'username': '123', 'password': '321'}
pwd = self.cleaned_data.get("password")
return md5(pwd)
# 使用modelfprm
# class LoginModelForm(forms.ModelForm):
# modelform需要去数据库里拿数据
# class Meta:
# model = models.Admin
# fields = ["username", "password"]
def login(request):
"""登陆"""
if request.method == "GET":
form = LoginForm()
return render(request, "login.html", {"form": form})
form = LoginForm(data=request.POST, )
if form.is_valid():
# 验证成功,获取到用户名和密码
# {'username': '123', 'password': '321',"code":"xxx"}
# print(form.cleaned_data) # form验证通过后只能form.cleaned_data验证
user_input_code = form.cleaned_data.pop("code")
code = request.session.get("img_code", "")
print("=========", user_input_code, code)
if code.upper() != user_input_code.upper():
form.add_error("code", "验证码错误")
return render(request, "login.html", {"form": form})
# 去数据库效验用户名和密码是否正确,获取用户对象,如果错的就是None
# filter(username="form.cleaned_data["username]",password="form.cleaned_data["password]")
admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
print("adin_object=", admin_object)
if not admin_object:
# form / modelform可以 主动的 手动添加错误信息,(字段名,错误信息)
form.add_error("password", "用户名或密码错误")
return render(request, "login.html", {"form": form})
# 用户名和密码输入正确
# 网站生成随机字符串,写到用户浏览器的cookie中,在写入到seesion中
request.session["info"] = {"id": admin_object.id, "name": admin_object.username} # 会自动生成cookie和在服务器生成session
request.session.set_expiry(60 * 60 * 24 * 7) # 7天免登陆
return redirect("/admin/list/") # 登陆成功后跳转的页面
return render(request, "login.html", {"form": form})
from io import BytesIO
def image_code(request):
"""生成验证码图片"""
# 调用code函数
img, code_string = check_code()
# print("img-code=", img, code_string)
# 写入到session中,以便于后续验证
request.session["img_code"] = code_string
# 设置验证码60秒超时
request.session.set_expiry(60)
# 创建实力对象
stream = BytesIO()
img.save(stream, "png") # 将图片保存到内存中
return HttpResponse(stream.getvalue()) # 再从内存获取图片
def logout(request):
"""注销"""
# 清除当前session
request.session.clear()
return redirect("/login/")
六. 编写html(APP-->templates-->login.html)
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.min.css' %}">
<style>
.account{
width:400px;
border: 1px solid #dddddd;
border-radius: 5px;
box-shadow: 5px 5px 20px #aaa;
margin-left:auto;
margin-right:auto;
margin-top:100px;
padding:20px 40px;
}
.account h2{
margin-top:10px;
text-align:center;
}
</style>
</head>
<body>
<div class="account">
<h2>用户登陆</h2>
<form method="post" novalidate>
{% csrf_token %}
<div class="form-group">
<label>用户名</label>
{{ form.username }}
<span style="color:red;">{{ form.username.errors.0}}</span>
</div>
<div>
<div class="form-group">
<label>密码</label>
{{ form.password }}
<span style="color:red;">{{ form.password.errors.0}}</span>
</div>
</div>
<div class="form-group">
<label>图片验证</label>
<div class="row">
<div class="col-xs-7">
{{ form.code}}
<span style="color:red;">{{ form.code.errors.0 }}</span>
</div>
<div class="col-xs-5">
<img id="image_code" src="/image/code/" style="width:125px;">
</div>
</div>
</div>
<input type="submit" value="登陆" class="btn btn-primary">
</form>
</div>
</body>
</html>