20.Django大型电商项目之登录页面、如何使用图片验证码

news2024/12/27 20:07:12

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),
]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/98130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Allegro打散Group的两种方法操作指导

Allegro打散Group的两种方法操作指导 Allegro可以建一个Group,也可以打散一个Group,当不需要器件,过孔走线等等以一个group形式体现,可以用下面的操作打散,具体操作如下 举例需要将这个Group打散 选择setup-application Mode-placement edit模式 Find选择Groups 鼠标移…

基于Geehy APM32F4移植使用letter-shell命令行终端

1. letter-shell简介 letter shell是一个C语言编写的&#xff0c;可以嵌入在程序中的嵌入式shell&#xff0c;主要面向嵌入式设备。 说得直白点他就是一个命令行交互软件&#xff0c;可以读取用户输入的命令&#xff0c;找到并执行命令对应的函数。 letter-shell的功能十分强…

C# 绘图基本方法

一得到Graphics对象 1 OnPaint事件中使用 Protected overrid void OnPaint(PaintEventArgs e) {Graphics ge.Graphics;...... }2 其他情况实现 Graphics gthis.CreaateGraphics();二 关于Graphics的释放 1 对于CreateGraphics&#xff08;&#xff09;得到的Graphics对象&a…

VC++开发一个资源编辑器-1.拖动控件

我想要做一个代码生成向导&#xff0c;首先要实现的功能 &#xff0c;是自动生成界面。 要实现以上的功能&#xff0c;第1步要实现&#xff0c;对界面上各个控件的拖动&#xff0c;移动&#xff0c;缩放的功能。 今天完成了初步的代码实现。 最要的功能实现 与备忘在这里写一…

【MQTT】mqtt 服务器部署--go 生产和消费demo

1. 背景 Golang 是谷歌开发的一种静态强类型、编译、并发和垃圾收集编程语言。围棋富有表现力&#xff0c;干净&#xff0c;高效。它的并发机制使得编写最大限度地利用多核和网络机器的程序变得容易&#xff0c;它的创新类型系统使得灵活和模块化的程序构造成为可能。Go 可以快…

【博客561】利用隧道和conntrack实现NAT网关

利用隧道和conntrack实现NAT网关 场景&#xff1a;实现一个NAT网关来转发其它node的出外网流量 如&#xff1a;图中的2节点充当NAT网关来转发1的出外网流量 利用隧道和conntrack实现NAT网关 节点ip&#xff1a; node1是172.17.158.48&#xff0c;node2是172.17.158.46 1、配…

Clipper库 | 类型和填充规则

裁剪类型(ClipType) CT_INTERSECTION 0 CT_UNION 1 CT_DIFFERENCE 2 CT_XOR 3交集&#xff0c;AND (intersection) &#xff1a;主体和裁剪多边形相交的区域。并集&#xff0c;OR (union) - 主体和裁剪多边形两者合并的区域。非/差&#xff0c;NOT (difference) - 裁剪多边…

net/http 库的客户端实现(上)

前言 Go语言标准库 net/http 是一个非常强大的标准库&#xff0c;使得构建 HTTP 请求和编写 Web 服务器的工作变得非常简单。 我们来看看是他是如何实现客户端和服务端的。 使用示例 假设本地有一个GET方法的HTTP接口&#xff0c;响应 Hello World&#xff01; 使用 net/ht…

Cesium:实时数据渲染性能优化与内存泄漏问题分析

在基于Cesium.js三维可视化开发框架,采用“轮询”策略,实现单车点位数据的实时渲染的demo示例,线上部署完毕之后,竟发现出现了“内存泄漏”的问题。思前想后,反复调试,然而并没有找到引发泄露的根源所在,最后偶然间在《JavaScript高级程序设计(第4版)》中看到了问题的答…

HashTable源码解析

HashTable源码解析 简介 HashTable 是一个古老的&#xff08;JDK1.0 时就已存在&#xff09;线程安全的容器&#xff0c;其核心方法都是 synchronized 修饰的。 相反 HashMap 不是线程安全的。 HashTable与HashMap对比 二者继承体系 HashTable HashMap 从图中可以对比得出…

零基础的小白如何学习编程,该怎么入手学习?

零基础的小白如何学习编程&#xff0c;该怎么入手学习&#xff1f;这是一个被问烂透而有很有趣的话题了。听到这个问题时&#xff0c;小编的第一反应就是要弄清楚对方为什么要学习编程&#xff0c;这是一个很好地起点&#xff0c;清楚自己想要什么&#xff0c;才能去努力实现。…

【JY】 ABAQUS子程序UEL的有限元原理与应用

不等待即关注【简述ABAQUS中UEL子程序】ABAQUS作为成熟的商用有限元软件&#xff0c;可为高级用户提供特定的分析需求。ABAQUS常见的二次开发子程序包括&#xff1a;UMAT、VUMAT、UGENS、UEL和VUEL等。其中UEL/VUEL分别适用于ABAQUS的Standard/Explicit求解器。只有清楚有限元分…

零基础怎么学Python编程,新手常犯哪些错误?

Python是人工智能时代最佳的编程语言&#xff0c;入门简单、功能强大&#xff0c;深获初学者的喜爱。 很多零基础学习Python开发的人都会忽视一些小细节&#xff0c;进而导致整个程序出现错误。下面就给大家介绍一下Python开发者常犯的几个错误。 1、错误的使用变量。 在Pyt…

华为网工入门之eNSP小实验(5)--VLAN间相互通信的三种方法

VLAN间相互通信 实际网络部署中一般会将不同IP地址段划分到不同的VLAN。同VLAN且同网段的PC之间可直接进行通信&#xff0c;无需借助三层转发设备&#xff0c;该通信方式被称为二层通信。VLAN之间需要通过三层通信实现互访&#xff0c;三层通信需借助三层设备(路由器,三层交换…

高可用系列文章之二 - 传统分层架构技术方案

前文链接 高可用系列文章之一 - 概述 - 东风微鸣技术博客 (ewhisper.cn) 三 技术方案 3.1 概述 单点是系统高可用最大的风险和敌人&#xff0c;应该尽量在系统设计的过程中避免单点。 保障系统的高可用, 方法论上&#xff0c;高可用保证的原则是「集群化」(或 「冗余」), …

LeetCode HOT 100 —— 312.戳气球

题目 有 n 个气球&#xff0c;编号为0 到 n - 1&#xff0c;每个气球上都标有一个数字&#xff0c;这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球&#xff0c;你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和 i…

别只关注chatGPT能不能写论文了,它还支持49中场景,代码都给你写好了,速领

简介 chatGPT最近非常不稳定&#xff0c;访问一不小心就出现了网络错误&#xff0c;根本就不能很好的使用。那么我们该怎么办呢&#xff1f;勇哥给大家想到了一个种办法&#xff0c;就是用程序去调用openapi的接口&#xff0c;这个接口虽然是收费的&#xff0c;但是可免费使用…

linux下源码编译cloudcompare(解决无法加载pcd文件的问题)

cloudcompare是一款点云处理软件&#xff0c;里面有很多算法&#xff0c;值得大家学习研究。 下面介绍linux下源码编译cloudcompare的方法。 1.安装依赖&#xff1a; sudo apt-get install doxygen sudo apt install cmake-curses-gui2.下载&#xff1a; git clone --recurs…

Qt之天气预报——界面优化篇(含源码+注释)

一、界面优化效果 下方为界面优化完成和优化前的效果对比。 优化前&#xff1a; 优化后&#xff1a; 二、优化内容 添加标题栏添加图片&#xff08;图图标素材源自阿里巴巴矢量图标库&#xff09;更新UI内容&#xff08;微调大小、布局比例&#xff09;添加鼠标事件函数&…

Java 教程

Java 教程 Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。 Java 可运行于多个平台&#xff0c;如 Windows, Mac OS 及其他多种 UNIX 版本的系统。 本教程通过简单的实例将让大家更好的了解 Java 编程语言。 移动操作系统 Android 大部分的代码采用…