dDjango 20购物商城项目

  • 1、安装pillow
  • 2、在注册页面加入验证码
    • 2.1、register.html (增加内容)
    • 2.2、register.js(增加内容)
    • 2.2、路由、视图(增加内容)
      • 2.2.1、路由
      • 2.2.2、视图
        • views_heiper.py(增加两个函数)
        • views.py
        • 点击注册后对比验证码
  • 3、这里我把注册时密码验证、页面返回等完善了一下
    • 3.1、增加了邮箱格式验证
    • 3.2、增加了密码格式验证
  • 4、登陆页面验证码
这里只展示代码,一些原理和细节可以参考我这篇博客https://blog.csdn.net/a__int__/article/details/103354549

1、安装pillow

pillow是一个生成图像的库

pip install Pillow

2、在注册页面加入验证码

2.1、register.html (增加内容)

这里我加在了“注册”按钮之前

            <span>验证码:</span><input id="verify_code" type="text" name="verify_code" placeholder="请输入图中的验证码"><img src="{% url 'axf:get_code' %}"><br>{% if verify_wrong %}<span id="verify_span" style="color: red">{{ verify_wrong }}</span>{% else %}<span id="verify_span" style="color: green"></span>{% endif %}<br><br>

2.2、register.js(增加内容)

点击图片更换

    $("img").click(function () {// 在浏览器里面路径不改变,这个图他就会不发生改变,所以给这个路径加一个随机数让浏览器知道改变了$(this).attr("src","/axf/getcode/?t="+Math.random());$("#verify_span").html("").css("color", "green");})

2.2、路由、视图(增加内容)

2.2.1、路由

2.2.2、视图
views_heiper.py(增加两个函数)
# 验证码,随机颜色
def get_color():return random.randrange(256)# 验证码,随机4个文字
def get_txt():txt = "zxcvbnmasdfghjklqwertyuiopZXCVBNMASDFGHJKLQWERTYUIOP1234567890"code = ""for i in range(4):code + random.choice(txt)return code
views.py

视图里新导入的库

增加函数get_code()

绘制:画板、文字、半圆弧

def get_code(request):"""Image 画板     ImageDraw 画笔"""color_bg = (get_color(), get_color(), get_color())# 设置画板的背景及大小image = Image.new(mode='RGB', size=(100, 50), color=color_bg)# 画笔绘制imagedraw = ImageDraw(image, mode='RGB')# 获取随机文字the_code = get_txt()# 把所有小写字母换成大写字母,存入session# 验证时同样大小写转换一遍,这样用户输入时可以不区分大小写upper_code = the_code.upper()request.session["the_code"] = upper_codefont = ImageFont.truetype("C:\Windows\Fonts\simsunb.ttf", 50)for i in range(4):# 文字填充色fill = (get_color(), get_color(), get_color())# 画笔在画板上绘制文字imagedraw.text(xy=(25 * i, 0), text=the_code[i], fill=fill, font=font)# 绘制1000个杂色点for i in range(1000):fill = (get_color(), get_color(), get_color())xy = (random.randrange(201), random.randrange(100))imagedraw.point(xy=xy, fill=fill)# 绘制向下的半圆弧"""drawObject.arc([x1, y1, x2, y2], startAngle, endAngle, options)在左上角坐标为(x1, y1),右下角坐标为(x2, y2)矩形区域内满圆O内,以starangle为起始角度,endAngle为终止角度,截取圆O的一部分圆弧画出来"""imagedraw.arc((random.randrange(0,10),6,80,random.randrange(70,100)), random.randrange(0,180),random.randrange(250,360), fill=get_color())fp = BytesIO()image.save(fp, "png")return HttpResponse(fp.getvalue(), content_type="image/png")

效果截图

点击注册后对比验证码

def register(request):# 请求if request.method == "GET":data = {"title": "注册"}return render(request, 'user/register.html', context=data)# 提交elif request.method == "POST":# 用户输入的验证码verify_code = request.POST.get("verify_code")verify_code = verify_code.upper()print("获取到验证码le")# session存的验证码the_code = request.session.get("the_code")if verify_code != the_code:data = {"verify_wrong": "验证码不对,重新输入"}return render(request, 'user/register.html', context=data)else:try:username = request.POST.get("username")email = request.POST.get("email")password = request.POST.get("password")icon = request.FILES.get("icon")password = make_password(password)user = AXFUser()user.u_name = usernameuser.u_password = passworduser.u_icon = iconuser.u_email = emailuser.save()# 用uuid得到唯一激活码,再哈希加密u_token = uuid.uuid4().hex# 缓存过期时间为1天cache.set(u_token, user.id, timeout=60 * 60 * 24)send_email_activate(username, email, u_token)except Exception as err:data = {"err": "数据异常"}return render(request, 'user/register.html', context=data)return redirect(reverse("axf:login"))

3、这里我把注册时密码验证、页面返回等完善了一下

下面是register.js目前完整代码

$(function () {T_change("#email_input", "#email_info", "邮箱可以用", "邮箱已存在", T_path = '/axf/checkemail/');T_change("#username_input", "#username_info", "用户名可用", "用户名已存在", T_path = '/axf/checkuser/');T_change("#password_input", "#password_info", "密码可用", "密码必须含有字母、数字、符号(+-.%#@*&!)三种", T_path = "/axf/checkpwd/");T_change("#password_confirm_input", "#password_confirm_info", "", "", T_path = "", is_password = 1);$("img").click(function () {// 在浏览器里面路径不改变,这个图他就会不发生改变,所以给这个路径加一个随机数让浏览器知道改变了$(this).attr("src", "/axf/getcode/?t=" + Math.random());$("#verify_span").html("").css("color", "green");});});function T_change(T_input, T_info, T_text1, T_text2, T_path = "", is_password = 0) {var $T_i = $(T_input);$T_i.change(function () {// val()返回被选元素的当前值,trim()的作用是去掉字符串两端的多余的空格var T_i = $T_i.val().trim();console.log(T_i);if (is_password === 1) {var $T_i_info = $(T_info);$T_i_info.html(T_text1).css("color", "green");} else {if (T_i.length) {// 将用户名发给服务器$.getJSON(T_path, {"T_name": T_i}, function (data) {var $T_i_info = $(T_info);if (data['status'] === 200) {$T_i_info.html(T_text1).css("color", "green");} else if (data['status'] === 901) {$T_i_info.html(T_text2).css("color", "red");} else if (data['status'] === 902) {$T_i_info.html(data['msg']).css("color", "red");}})}}})
}function check() {username = check_one("#username_input", "#username_info", "用户名不能为空");email_o = check_one("#email_input", "#email_info", "邮箱不能为空");password_o = check_one("#password_input", "#password_info", "密码不能为空");password_t = check_one("#password_confirm_input", "#password_confirm_info", "请再次输入密码");var $password_input = $("#password_input");var password = $password_input.val().trim();var $password_confirm = $("#password_confirm_input");var password_confirm = $password_confirm.val().trim();var $email_input = $("#email_input");var email = $email_input.val().trim();// 密码输入后md5加密后提交(注意:这里是前端加密,传入后台的时候还会再加密一次)if (password_o === 0 || password_t === 0) {if (password === password_confirm) {console.log("两次密码输入一致");if (password === email) {$("#password_info").html("密码不能和邮箱一样").css("color", "red");$("#password_confirm_info").html("密码不能和邮箱一样").css("color", "red");return false} else {$password_input.val(hex_md5(password));$password_confirm.val(hex_md5(password));$("#password_confirm_info").html("").css("color", "green");}} else {$("#password_confirm_info").html("两次密码输的不一样").css("color", "red");return false}}return !(username + email_o + password_o);
}function check_one(C_input, C_info, C_text) {var $username_info = $(C_info);var $username = $(C_input);var username = $username.val().trim();var info_color = $username_info.css("color");// 检查是否为空if (!username) {$username_info.html(C_text).css("color", "red");return 1}// 检查是否有重复if (info_color === 'rgb(255, 0, 0)' || info_color === 'rgb(51, 51, 51)') {console.log(C_input);console.log("颜色不对");return 1}return 0
}

下面是register.html目前完整代码

{% extends "base_user.html" %}
{% load static %}
{% block ext_css %}{{ block.super }}<link rel="stylesheet" href="{% static 'axf/user/css/register.css' %}">
{% endblock %}
{% block ext_js %}{{ block.super }}<script type="text/javascript" src="{% static 'axf/user/js/register.js' %}"></script>
{% endblock %}
{% block footer %}<div class="title"><a href="#" onclick="javascript:history.back(-1);"><div class="arrow-box nav-left">返回</div></a><p class="font">用户注册</p></div>
{% endblock %}
{% block content %}<div class="container">{% if err %}<span>{{ err }}</span>{% endif %}<form method="POST" enctype="multipart/form-data" action="{% url 'axf:register' %}" onsubmit="return check()">{% csrf_token %}<div class="form-group"><label for="username_input" id="label_red">用户名</label><input name="username" type="text" class="form-control" id="username_input" placeholder="请输入用户名"><span id="username_info"></span></div><div class="form-group"><label for="email_input" id="label_red">&nbsp;邮箱</label><input name="email" type="text" class="form-control" id="email_input" placeholder="请输入邮箱"><span id="email_info"></span></div><div class="form-group"><label for="password_input" id="label_red">密码</label><input name="password" type="password" class="form-control" id="password_input" placeholder="请输入密码"><span id="password_info"></span></div><div class="form-group"><label for="password_confirm_input" id="label_red">确认密码</label><input type="password" class="form-control" id="password_confirm_input" placeholder="请再次输入密码"><span id="password_confirm_info"></span></div><div class="form-group"><label for="icon_input">&nbsp;头像</label><input name="icon" type="file" id="icon_input" placeholder="请再次输入密码"></div><br><span>验证码:</span><input id="verify_code" type="text" name="verify_code" placeholder="请输入图中的验证码"><img src="{% url 'axf:get_code' %}"><br>{% if verify_wrong %}<span id="verify_span" style="color: red">{{ verify_wrong }}</span>{% else %}<span id="verify_span" style="color: green"></span>{% endif %}<br><br><button type="submit" class="btn btn-success btn-block">注册</button></form><br><br><br><br></div>
{% endblock %}

下面是register.css目前完整代码

header{height: 0rem;margin-bottom: 0rem;
}.title {top:0;position: fixed;width: 100%;height: 50px;background-color: #009688;
}.font {color: #fff;line-height: 50px;font-size: 20px;text-indent: -2em;text-align: center
}.nav-left {float: left;
}.arrow-box{width: 50px;height: 26px;position: relative;border-radius: 10% 10%;background: #fff;text-align: center;line-height: 26px;top: 12px;font-size: 14px;left: 10px;
}
#label_red:before {content: "*";color: red;
}
.container{margin-top: 2rem;
}

页面截图

3.1、增加了邮箱格式验证

视图里的 def check_email(request)

def check_email(request):email = request.GET.get("T_name")e = AXFUser.objects.filter(u_email=email)data = {"status": HTTP_OK,"msg": '邮箱可用',}# exists()判断路径是否存在if e.exists():data["status"] = HTTP_USER_EXISTdata["msg"] = '邮箱已经存在'else:# 邮箱规则x@x.x 最后一个x需为com,.cn,.net,.org..等if re.match("[A-Za-z0-9]+@[A-Za-z0-9]+\.[cmnoetrg]+", email):passelse:data["status"] = 902data["msg"] = '邮箱格式不正确'return JsonResponse(data=data)

3.2、增加了密码格式验证

新增路由

视图新增函数


def check_pwd(request):pwd = request.GET.get("T_name")data = {}l_re = re.compile('[a-zA-Z]')num_re = re.compile('[0-9]')p_re = re.compile('[\.\?\!\=\-\+\_\|\*\&\%\#\@\~\@\!\%\¥]')wrong_re = re.compile('[^a-zA-Z0-9\.\?\!\=\-\+\_\|\*\&\%\#\@\~\@\!\%\¥]')if len(pwd) < 6 or len(pwd) > 20:data["status"] = 902data["msg"] = '请输入6到20位的密码'elif wrong_re.search(pwd) != None:data["status"] = 902data["msg"] = '密码中包含了无效字符'else:if l_re.search(pwd) == None:data["status"] = 902data["msg"] = '密码里必须包含字母'elif num_re.search(pwd) == None:data["status"] = 902data["msg"] = '密码里必须包含数字'elif p_re.search(pwd) == None:data["status"] = 902data["msg"] = '密码里必须包含.?!=-+_|*&%#@~¥中至少一个符号'else:data["status"] = 200data["msg"] = '该密码可以使用'return JsonResponse(data=data)

4、登陆页面验证码

login.html(增加了三处:css样式新增、头部、验证码,代码和注册页面里的一样)


login.css(新建文件,内容和注册页面的css一模一样)

header{height: 0rem;margin-bottom: 0rem;
}.title {top:0;position: fixed;width: 100%;height: 50px;background-color: #009688;
}.font {color: #fff;line-height: 50px;font-size: 20px;text-indent: -2em;text-align: center
}.nav-left {float: left;
}.arrow-box{width: 50px;height: 26px;position: relative;border-radius: 10% 10%;background: #fff;text-align: center;line-height: 26px;top: 12px;font-size: 14px;left: 10px;
}
#label_red:before {content: "*";color: red;
}
.container{margin-top: 2rem;
}

视图(和注册页面的视图函数基本一样)

这是登录视图函数完整代码

def login(request):if request.method == "GET":error_msg = request.session.get('error_msg')data = {"title": "登录"}if error_msg:# 如果session['error_msg']存在就删除,并将error_msg显示在页面上del request.session['error_msg']data['error_msg'] = error_msgreturn render(request, 'user/login.html', context=data)elif request.method == "POST":# 用户输入的验证码verify_code = request.POST.get("verify_code")# 把小写字母全部换成大写字母verify_code = verify_code.upper()print("获取到验证码le")# session存的验证码the_code = request.session.get("the_code")if verify_code != the_code:data = {"verify_wrong": "验证码不对,重新输入"}return render(request, 'user/login.html', context=data)else:username = request.POST.get("username")password = request.POST.get("password")users = AXFUser.objects.filter(u_name=username)# exists()方法主要是判断查询的数据是否存在,存在时返回True,否则返回False# first() 返回queryset中匹配到的第一个对象,如果没有匹配到对象则为Noneif users.exists():user = users.first()if check_password(password, user.u_password):if user.is_active:request.session['user_id'] = user.idreturn redirect(reverse('axf:mine'))else:request.session['error_msg'] = '未激活'return redirect(reverse('axf:login'))else:# 密码错误request.session['error_msg'] = '密码错误'return redirect(reverse('axf:login'))# 用户名不存在request.session['error_msg'] = '用户不存在'return redirect(reverse('axf:login'))

Django 20购物商城项目(注册、登录页面:生成动态验证码)相关推荐

  1. Django 19购物商城项目(收货地址:添加、修改)

    dDjango 19购物商城项目 1.新建axf_addr,收货地址表 2.路由 3.cart页面,添加默认收货地址 4.视图(主要修改了cart.新建了收货地址相关方法) 5.收货地址列表 6.收货 ...

  2. [golang gin框架] 29.Gin 商城项目-用户登录,注册操作

    一.用户登录,注册界面展示说明 先看登录,注册界面以及相关流程,再根据流程写代码,一般网站的登录,注册功能都会在一个页面进行操作,还有的是在几个页面进行操作,这里讲解在几个页面进行注册的操作,步骤如下 ...

  3. Vue购物商城项目(二) 数据请求使用

    Vue购物商城项目(二) 文章目录 Vue购物商城项目(二) 前言 一.请求数据 request.js home.js Home.vue 二.使用数据 总结 前言 1.这里面包含了大量的.我的个人理解 ...

  4. python学习第八天---用Django框架创建可重用注册登录系统

    python学习第八天---用Django框架创建可重用注册登录系统 实现的功能 项目开始前的整体规划 搭建环境完成基础配置 创建app 更改语言和时区 数据库表生成 启动开发服务器 浏览器访问,检测 ...

  5. SpringSecurity+Mybatis实现用户自助注册登录(含角色),打造简单安全的注册登录页面。

    #项目架构.功能点 架构: Springboot2.5.+ MySQL数据库8.0+(记录用户信息.角色清单.用户角色对照表) 持久层Mybatis 用户注册页面RegisterPage采用Thyme ...

  6. Android注册登录页面

    Android注册登录页面 需求 分析 项目目录 .java domain JsonBean.java UserInfo.java utils GetJsonDataUtil.java Login.j ...

  7. 用vue+element-ui快速写一个注册登录页面

    vue+element-ui可以快速开发一个页面,免除大部分的css代码. 一.用表单来做: 1.代码: <!--基本html代码区域--> <template><div ...

  8. 原生js验证简洁美观注册登录页面

    本文转载自: https://www.cnblogs.com/storm-chou/p/6189489.html 作者:storm-chou 转载请注明该声明. 序 一个以js验证表单的简洁的注册登录 ...

  9. 设计灵感|APP注册登录页面的设计形式

    注册登录页面是一个APP的门面,它的好坏与否直接影响着APP的用户数和用户体验. 作为一个设计师,其实经常时不时就会去下载一些APP,体验的时候经常被一些不尽人意的注 册登录页面弄的想怒摔手机,最终都 ...

最新文章

  1. 2020-11-11(aidl)
  2. python 只取数值_Python:你会生成列表吗?-- 列表生成式
  3. 《数据库原理与应用》(第三版) 第 6 章 数据操作语句 基础 习题参考答案
  4. mysql5.6安装51cto_MySQL 5.6 for Windows配置安装之解压缩版
  5. python打包成.exe程序
  6. linux 压缩为多个文件,在Linux中,如何将输入流压缩为多个输出文件?
  7. 网站安全配置---挂载路由导航
  8. Python拓展12(使配置文件生效ConfigParser模块)
  9. 【习题基础知识】输入与输出、简单循环(好多图贴上去好累...要看图的话我把word文档发给你)...
  10. 软件开发过程中的一些感悟
  11. 【干货分享】硬件测试工程师必备基本技能,看这一篇就够!
  12. 产品线架构设计的基本步骤
  13. 强化学习个人学习总结
  14. 2021-05-16
  15. 云主机如何保证信息安全?
  16. 浪漫又务实的华为自研之路: 始于情怀,终于智能
  17. 【从0到1搭建LoRa物联网】19、LoRa串口透传例程(补充)
  18. react中 Ender键 触发事件数(输入框)
  19. 小程序实现TreeView树多选功能
  20. 关于二元函数是否可微的条件及其计算方法——高等数学

热门文章

  1. 微软2.4亿美元赢得Facebook1.6%股份收购权
  2. ERP行业内幕看了这五个问题全懂了
  3. 零跑股价成绩突出,实现逆风翻盘
  4. Fidder工具详解
  5. 四个s级的在线网站分享,那些需要收费的要被哭死!
  6. 233、一个宽带装两个路由器怎么设置
  7. 魔兽争霸III - 十大魔法排行榜
  8. Vision Transformer with Deformable Attention可变形注意力
  9. Iterator(JFIS)
  10. jstl+el(JFIS)