python + django 搭建页面---图片验证码


前言

上文已经实现了登录页面的基本逻辑,现在我们来实现图片验证码

图片验证码

网上有太多教程,就直接放图片验证码的实现函数了。
我们要操作的是创建utils文件夹,里面创建code.py文件,放check_code函数,check_code的font_file需要传入一个字符文件ttf,网上随便下载一个导入即可,其他字段默认值根据自己需要改变。

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter


# "C:\Users\24119\Desktop\pyweb\web\static\font\AaManYuShouXieTi.ttf"
# 参数已经写的很清楚了
def check_code(font_file, width=120, height=30, char_length=4, font_size=28):
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    def rndChar():
        """
        生成随机字母   
        :return:
        """
        return chr(random.randint(65, 90))

    def rndColor():
        """
        生成随机颜色
        :return:
        """
        return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))

    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text([i * width / char_length, h], char, font=font, fill=rndColor())

    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())

    # 写干扰圆圈
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())

    # 画干扰线
    for i in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)

        draw.line((x1, y1, x2, y2), fill=rndColor())

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img, ''.join(code)


# if __name__ == '__main__':
#     # 1. 直接打开
#     img, code = check_code()
#     print(code)
#     img.show()

    # 2. 写入文件
    # img,code = check_code()
    # with open('code.png','wb') as f:
    #     img.save(f,format='png')

    # 3. 写入内存(Python3)
    # from io import BytesIO
    # img,code = check_code()
    # stream = BytesIO()
    # img.save(stream, 'png')
    # stream.getvalue()

    # 4. 写入内存(Python2)
    # import StringIO
    # stream = StringIO.StringIO()
    # img.save(stream, 'png')
    # stream.getvalue()

然后在urls.py中添加路径

from django.urls import path

from web import views

urlpatterns = [
    # path('admin/', admin.site.urls),
    path('login/', views.login),
    path('image/code/', views.img_code),
]
在这里插入代码片

在views.py中定义函数

from django.shortcuts import render, redirect, HttpResponse
from io import BytesIO
from web import models

def img_code(request):
    # 调用check_code()函数
    img, code_string = check_code(font_file='web/static/font/AaManYuShouXieTi.ttf')
    stream = BytesIO()
    img.save(stream, 'png')
    # 返回的是图像,当然我们还取到了一个code_string,是图片验证码的原字符,这用来和前端输入的验证码进行比较
    return HttpResponse(stream.getvalue())

在login.html文件中添加验证码区域

<!DOCTYPE html>
<html>
<head>
    <title>Japan_is_shit</title>
</head>
<body>
    <div>
        <h2>用户登陆</h2>
        <!-- 表单 -->
        <form method="post">
            <!-- django默认在post请求加一个csrf_token值,不加{% csrf_token %}会报错 -->
            {% csrf_token %}



            <div>
                <label>用户名</label>
                <div>
                    <input type="" name="user">
                </div>
            </div>



            <div>
                <label>密码</label>
                <div>
                    <input type="" name="pwd">
                </div>
            </div>
            
            {#验证码#}
            <div>
                <label>验证码</label>
                <img src="/image/code/">
                <div>
                    <input type="" name="code">
                </div>
            </div>


            <div>
                <div>
                    <!-- 错误信息 -->
                    <span>{{error_msg}}</span>
                    <button>登录</button>
                </div>
            </div>




        </form>
    </div>
</body>
</html>

实现效果如下图所示
在这里插入图片描述那现在的任务就是写登录逻辑,让我们去到views.py 中写验证图片验证码的登录逻辑:验证码应该是最先被验证的,验证码不通过,直接提示验证码不通过,验证码通过后才验证用户名和密码。

对此做出的改变是在img_code函数中把code_string定义为全局变量,并在login函数中调用code_string与获取的code字段进行比较(大小写一致),不同就重新返回带提示的login.html页面,相同就验证用户和密码。

from django.shortcuts import render, redirect, HttpResponse

from io import BytesIO
# Create your views here.
from web import models

# 用request方式
from web.utils.code import check_code

code_string = ''


def img_code(request):
    # 声明全局字段
    global code_string
    # 调用check_code()函数
    img, code_string = check_code(font_file='web/static/font/AaManYuShouXieTi.ttf')
    stream = BytesIO()
    img.save(stream, 'png')
    # 返回的是图像,当然我们还取到了一个code_string,是图片验证码的原字符,这用来和前端输入的验证码进行比较
    return HttpResponse(stream.getvalue())


def login(request):
    # 如果请求方式是get,就返回本页面,否则(post方式)就获取页面提交的内容
    # 和数据库的用户名/密码做对比,相同就登录,不同就报错
    if request.method == "GET":
        return render(request, 'login.html')
    # user对应html文件<input type="" name="user">输入框,pwd同理
    name = request.POST.get('user')
    pwd = request.POST.get('pwd')
    code = request.POST.get('code')
    # 都转化为小写进行比较
    if code.upper() != code_string.upper():
        return render(request, 'login.html', {"error_msg": "验证码错误"})
    # 从数据库web中的web_userinfo表中取出所有数据
    data_list = models.Admin.objects.all()
    # 从每条数据中取得name和password字段进行比较
    for data in data_list:
        if data.username == name and data.password == pwd:
            # 登录成功跳转到我主页
            return redirect('https://blog.csdn.net/qq_43504837')
    # 登录不成功就返回本页面,并给出错误信息
    return render(request, 'login.html', {"error_msg": "用户名或错误"})

总结

给页面加图片验证码的过程:
1.确保有一个生成图片验证码的函数check_code
2.在urls.py中添加路径image/code/ ,并映射函数img_code
3.在views.py 中添加img_code函数
4.在 img_code 函数中利用check_code生成图片和字符
5.图片写入返回前端,字符则用来与前端传过来的验证码比较
6.验证码比较通过,才比较用户和密码

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值