1. 登录页面
1.1 基础搭建
templates
<!-- netshop\userapp\templates\userapp\login.html -->
{% extends 'base.html' %}
{% block title %}用户登录页面{% endblock %}
{% load static %}
{% block headerjs %}
<script type="text/javascript" src="{% static 'js/md5-min.js' %}"></script>
{% endblock %}
{% block main %}
<div class="login-body">
<div class="login-card">
<div class="login-top">
<h3>新用户登录</h3>
<h5>尊敬的用户,欢迎您回来!</h5>
</div>
<div class="login-bottom">
<form method="post" action="http://127.0.0.1:8000/user/login/" onsubmit="login();">
<input type="hidden" name="time" id="time">
<div class="login-input-box">
<input type="hidden" name="csrfmiddlewaretoken"
value="Bk9p9oIn87TIw7edTgOWAyjWHDRZOOts0scYwmO9rCQau6nNudBBS3NFtbK5gLk1">
<input type="text" id="account" name="account" value="" class="login-admin active"
placeholder="邮箱登录">
<span style="color:red;" id="aSpan"></span>
<input type="password" id="password" name="password" value="" class="login-password">
<span style="color:red;" id="pSpan"></span>
<input type="text" style="height:36px;width: 100px;" id="code" onblur="checkCode(this.value)"><img
src="./首页_files/saved_resource" onclick="changeCode(this)"><span style="color:red;"
id="cSpan"></span>
<input type="hidden" name="redirect" value="">
<input type="hidden" name="cartitems" value="None">
<button class="login-btn" style="color: white;text-decoration: none;cursor: pointer">登录</button>
</div>
</form>
<div class="login-img">
<img src="{% static 'images/login_05.png' %}" alt="">
</div>
</div>
</div>
</div>
{% endblock %}
{% block footerjs %}
<script>
function isEmail(str) {
var reg = /^[a-zA-Z0-9_-]{6,}@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return reg.test(str);
}
function login() {
//获取输入框的值
var account = $('#account').val();
var password = $('#password').val();
//简单校验
if (account.length < 6 || !isEmail(account)) {
$('#aSpan').text('邮箱长度不能小于六位');
return false;
}
if (password.length < 6) {
$('#pSpan').text('密码长度不能小于六位');
return false;
}
var code = $('#code').val();
var cflag = checkCode(code);
if (!cflag) {
$('cSpan').text('×');
return false;
}
var time = new Date().getTime();
$('#time').val(time)
var hex_pwd = hex_md5(password);
//var hex_pwd = hex_md5(password+time)
$('#password').val(hex_pwd);
}
//切换验证码
function changeCode(obj) {
$(obj).attr('src', '/user/vcode/?r=' + new Date().getTime())
}
function checkCode(txt) {
var cflag = false;
$.ajax({
url: '/user/checkcode/',
type: 'get',
data: { 'code': txt },
async: false,
success: function (result) {
var flag = result.checkFlag;
if (flag) {
cflag = true;
$('cSpan').text('√');
} else {
$('cSpan').text('×');
}
}
})
return cflag;
}
</script>
{% endblock %}
views
# netshop\userapp\views.py
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from userapp.models import *
import jsonpickle
# 用户登录
class LoginView(View):
def get(self,request):
return render(request, 'userapp/login.html')
def post(self, request):
pass
urls
# netshop\userapp\urls.py
from django.contrib import admin
from django.urls import path,include
from userapp import views
urlpatterns = [
path('register/',views.Register.as_view()),
path('center/',views.userCenter),
path('login/',views.LoginView.as_view())
]
1.2 captcha生成验证码
生成验证码函数
#encoding=utf-8
import random
from PIL import Image,ImageDraw,ImageFont,ImageFilter
#生成几位数的验证码
from io import BytesIO
number = 4
#生成验证码图片的高度和宽度
size = (129,53)
#背景颜色,默认为白色
bgcolor = (255,255,255)
#字体颜色,默认为蓝色
fontcolor = (0,0,0)
#干扰线颜色。默认为红色
linecolor = (0,0,0)
#是否要加入干扰线
draw_line = True
#加入干扰线条数的上下限
line_number = (1,5)
#用来随机生成一个字符串
def gene_text():
# source = list(string.letters)
# for index in range(0,10):
# source.append(str(index))
source = ['0','1','2','3','4','5','6','7','8','9']
# source = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H','I','J', 'K','L', 'M', 'N','O','P','Q','R',
# 'S', 'T', 'U', 'V', 'W', 'Z','X', 'Y']
return ''.join(random.sample(source,number))#number是生成验证码的位数
#用来绘制干扰线
def gene_line(draw,width,height):
# begin = (random.randint(0, width), random.randint(0, height))
# end = (random.randint(0, width), random.randint(0, height))
begin = (0, random.randint(0, height)) # 起点
end = (74, random.randint(0, height)) # 终点
draw.line([begin, end], fill = linecolor,width=3)
#生成验证码
def gene_code():
width,height = size #宽和高
image = Image.new('RGBA',(width,height),bgcolor) #创建图片
import os
path = os.path.join(os.getcwd(),'utils','Arial.ttf')
font = ImageFont.truetype(path,36) #验证码的字体
draw = ImageDraw.Draw(image) #创建画笔
text = gene_text() #生成字符串
font_width, font_height = font.getsize(text)
draw.text(((width - font_width) / number, (height - font_height) / number),text,\
font= font,fill=fontcolor) #填充字符串
if draw_line:
gene_line(draw,width,height)
image = image.transform((width+30,height+10), Image.AFFINE, (1,-0.3,0,-0.1,1,0),Image.BILINEAR) #创建扭曲
# image = image.transform((width+20,height+10), Image.AFFINE, (1,-0.3,0,-0.1,1,0),Image.BILINEAR) #创建扭曲
image = image.filter(ImageFilter.EDGE_ENHANCE_MORE) #滤镜,边界加强
# image = image.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强
bytes = BytesIO() # 内存
image.save(bytes,format='png') # 保存验证码图片
return bytes.getvalue(),text # 获得二进制数据,
views
# netshop\userapp\views.py
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from userapp.models import *
import jsonpickle
from utils.code import gene_text
# 加载验证码
def loadCode(request):
from captcha.image import ImageCaptcha
image = ImageCaptcha()
# 获取生成验证码字符串
code = gene_text()
imageObj = image.generate(code)
# 返回图片
return HttpResponse(imageObj, content_type='image/png')
templates修改
<input type="text" style="height:36px;width: 100px;" id="code" onblur="checkCode(this.value)"><img src="/userapp/loadCode/" onclick="changeCode(this)"><span style="color:red;" id="cSpan"></span>
//切换验证码
function changeCode(obj) {
$(obj).attr('src', '/userapp/loadCode/?r=' + new Date().getTime())
}
1.3 校验输入的验证码是否正确
1.3.1如何实现验证验证码是否正确(前后端)
将正确的验证码存储到session中。我们在视图函数中编写一个验证功能,获取session中的验证码和输入框填写的验证码,验证后返回布尔值。
在前端的图片后,显示正确or错误,放一个onblur标签,调用前端的函数,前端函数的作用就是利用ajax发送同步请求,调用后端的验证功能,如果验证结果通过显示正确,反之错误。
1.3.2 代码展示
views
# 加载验证码
def loadCode(request):
from captcha.image import ImageCaptcha
image = ImageCaptcha()
# 获取生成验证码字符串
code = gene_text()
# 将code存放到session中
request.session['session_code'] = code
imageObj = image.generate(code)
# 返回图片
return HttpResponse(imageObj, content_type='image/png')
# 校验输入的验证码是否正确
def checkCode(request):
# 获取输入的验证码
code = request.GET.get('code',-1)
print(code)
print(type(code))
# 获取session对象中保存的正确的验证码
session_code = request.session.get('session_code',-2)
print('session_code',session_code)
print(type(session_code))
# 判断是否相等
vflag = False
if code == session_code:
vflag = True
# 返回响应
return JsonResponse({'vflag':vflag})
templates
function checkCode(txt) {
var cflag = false;
$.ajax({
url: '/userapp/checkCode/',
type: 'get',
data: { 'code': txt },
async: false,
success: function (result) {
var flag = result.vflag;
if (flag) {
cflag = true;
$('#cSpan').text('√');
} else {
$('#cSpan').text('×');
}
}
})
return cflag;
}
1.4 验证通过访问登录视图
views
# netshop\userapp\views.py
from django.shortcuts import render,HttpResponse,redirect
from django.http import JsonResponse
from django.views import View
from userapp.models import *
import jsonpickle
from utils.code import gene_text
# Create your views here.
# 注册视图类
class Register(View):
def get(self,request):
# 跳转到注册页面
return render(request, 'userapp/register.html')
def post(self,request):
# 完成注册
# 1.获取表单数据
uname = request.POST.get('account','')
pwd = request.POST.get('password','')
# 2.查询数据库是否已有该用户
try:
user = UserInfo.objects.get(uname=uname, pwd=pwd)
return render(request,'userapp/register.html')
except UserInfo.DoesNotExist:
user = UserInfo.objects.create(uname=uname, pwd=pwd)
request.session['user'] = jsonpickle.dumps(user) # 把用户对象序列化为字符串
return redirect('/userapp/center/') # 重定向到用户中心(路由地址)
# 用户中心
def userCenter(request):
return render(request, 'userapp/center.html')
# 用户登录
class LoginView(View):
def get(self,request):
return render(request, 'userapp/login.html')
def post(self, request):
# 获取请求参数
uname = request.POST.get('account','')
pwd = request.POST.get('password','')
# 根据输入的账户和密码查询数据是否存在该用户
user = UserInfo.objects.filter(uname=uname, pwd=pwd)[0]
# 如果有该用户,将用户存储到session种,跳转到个人页面;否则跳转到登陆页面
if user:
request.session['user'] = jsonpickle.dumps(user) # 把用户对象序列化为字符串
return redirect('/userapp/center/')
return redirect('/userapp/login/')
# 加载验证码
def loadCode(request):
from captcha.image import ImageCaptcha
image = ImageCaptcha()
# 获取生成验证码字符串
code = gene_text()
# 将code存放到session中
request.session['session_code'] = code
imageObj = image.generate(code)
# 返回图片
return HttpResponse(imageObj, content_type='image/png')
# 校验输入的验证码是否正确
def checkCode(request):
# 获取输入的验证码
code = request.GET.get('code',-1)
print(code)
print(type(code))
# 获取session对象中保存的正确的验证码
session_code = request.session.get('session_code',-2)
print('session_code',session_code)
print(type(session_code))
# 判断是否相等
vflag = False
if code == session_code:
vflag = True
# 返回响应
return JsonResponse({'vflag':vflag})
templates
<!-- netshop\userapp\templates\userapp\login.html -->
{% extends 'base.html' %}
{% block title %}用户登录页面{% endblock %}
{% load static %}
{% block headerjs %}
<script type="text/javascript" src="{% static 'js/md5-min.js' %}"></script>
{% endblock %}
{% block main %}
<div class="login-body">
<div class="login-card">
<div class="login-top">
<h3>新用户登录</h3>
<h5>尊敬的用户,欢迎您回来!</h5>
</div>
<div class="login-bottom">
<form method="post" action="/userapp/login/" onsubmit="return login();">
<input type="hidden" name="time" id="time">
<div class="login-input-box">
{% csrf_token %}
<input type="text" id="account" name="account" value="" class="login-admin active"
placeholder="邮箱登录">
<span style="color:red;" id="aSpan"></span>
<input type="password" id="password" name="password" value="" class="login-password">
<span style="color:red;" id="pSpan"></span>
<input type="text" style="height:36px;width: 100px;" id="code" onblur="checkCode(this.value)"><img src="/userapp/loadCode/" onclick="changeCode(this)"><span style="color:red;" id="cSpan"></span>
<input type="hidden" name="redirect" value="">
<input type="hidden" name="cartitems" value="None">
<button class="login-btn" style="color: white;text-decoration: none;cursor: pointer">登录</button>
</div>
</form>
<div class="login-img">
<img src="{% static 'images/login_05.png' %}" alt="">
</div>
</div>
</div>
</div>
{% endblock %}
{% block footerjs %}
<script>
function isEmail(str) {
var reg = /^[a-zA-Z0-9_-]{6,}@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
return reg.test(str);
}
function login() {
//获取输入框的值
var account = $('#account').val();
var password = $('#password').val();
var flag = true;
//简单校验
if (account.length < 6 || !isEmail(account)) {
$('#aSpan').text('邮箱格式不正确');
flag = false;
}
if (password.length < 6) {
$('#pSpan').text('密码长度不能小于六位');
flag = false;
}
var code = $('#code').val();
var cflag = checkCode(code);
if (!cflag) {
$('#cSpan').text('×');
return false;
}
if(!flag){
return false;
}
var hex_pwd = hex_md5(password);
//var hex_pwd = hex_md5(password+time)
$('#password').val(hex_pwd);
return true
}
//切换验证码
function changeCode(obj) {
$(obj).attr('src', '/userapp/loadCode/?r=' + new Date().getTime())
}
function checkCode(txt) {
var cflag = false;
$.ajax({
url: '/userapp/checkCode/',
type: 'get',
data: { 'code': txt },
async: false,
success: function (result) {
var flag = result.vflag;
if (flag) {
cflag = true;
$('#cSpan').text('√');
} else {
$('#cSpan').text('×');
}
}
})
return cflag;
}
</script>
{% endblock %}
urls.py
# netshop\userapp\urls.py
from django.contrib import admin
from django.urls import path,include
from userapp import views
urlpatterns = [
path('register/',views.Register.as_view()),
path('center/',views.userCenter),
path('login/',views.LoginView.as_view()),
path('loadCode/',views.loadCode),
path('checkCode/',views.checkCode),
]