欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Django 使用图片验证码进行登录

程序员文章站 2022-06-28 17:11:27
Day 20/12/30图片验证码登录生成图片验证码pip install pillow# -*- coding = utf-8 -*-# @Time : 2020/12/29 16:09# @Author : Chenih# @File : image_code.py# @Software : PyCharmfrom PIL import Image, ImageDraw, ImageFilter, ImageFontimport random"""绘制图片验证码"""...

Day 20/12/30

Django 使用图片验证码进行登录

图片验证码登录

生成图片验证码

pip install pillow
# -*- coding = utf-8 -*-
# @Time : 2020/12/29 16:09
# @Author : Chenih
# @File : image_code.py
# @Software : PyCharm

from PIL import Image, ImageDraw, ImageFilter, ImageFont


import random

"""绘制图片验证码"""
def check_code(width=120, height=30, char_length=5, font_file='kumo.ttf', 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__':
    image_obj, code = check_code()
	image_obj.show()  # 直接打开
    
    # 2. 写入文件
    # img,code = check_code()
    # with open('code.png','wb') as f:
    #     img.save(f,format='png')
 
    # 3. 写入内存
    # from io import BytesIO
    # stream = BytesIO()
    # img.save(stream, 'png')
    # stream.getvalue()

图片验证码路由

path('image/code/', account.image_code, name='image_code')

验证码图片的视图函数

def image_code(request):
    """生成图片验证码"""
    # 调用函数生成图片验证码
    image_obj, code = check_code()
    # 将验证码字符存入session
    request.session['code'] = code
    request.session.set_expiry(60)

    # 创建一个内存空间
    stream = BytesIO()
    # 将生成的图片验证码保存在内存空间中
    image_obj.save(stream, 'png')

    # 将从内存空间获取的图片验证码传给前端
    return HttpResponse(stream.getvalue())

页面显示

{% extends 'layout/basic.html' %}
{% load static %}

{% block title %} 邮箱|手机号 登录 {% endblock %}


{% block css %}
    <link rel="stylesheet" href="{% static 'css/account.css' %}">
    <style>
        .error-msg {
            color: red;
            position: absolute;
            font-size: 13px;
        }
    </style>
{% endblock %}


{% block content %}
    <div class="account">
        <div class="title">邮箱|手机号 登录</div>
        <form id="smsForm" method="POST" novalidate>
            {% csrf_token %}
            {% for field in form %}
                {% if field.name == 'code' %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        <div class="row">
                            <div class="col-xs-7">
                                {{ field }}
                                <span class="error-msg">{{ field.errors.0 }}</span>
                            </div>
                            <div class="col-xs-5">
                                {# 从image_code中拿到生成的图片 #}
                                <img src="{% url 'image_code' %}" id="imageCode" title="点击更换图片" alt="">
                            </div>
                        </div>
                    </div>
                {% else %}
                    <div class="form-group">
                        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
                        {{ field }}
                        <span class="error-msg">{{ field.errors.0 }}</span>
                    </div>
                {% endif %}
            {% endfor %}

        <div>
            <div style="float: right">
                <a href="{% url 'loginsms' %}">短信验证码登录?</a>
            </div>
        </div>

            <div class="row">
                <div class="col-xs-3">
                    <input type="submit" class="btn btn-primary" value="登  录"/>
                </div>
            </div>
        </form>
    </div>
{% endblock %}

{% block js %}
    <script>
        $(function () {
            $('#imageCode').click(function () {
                var oldSrc = $(this).attr('src');
                $(this).attr('src', oldSrc + '?');
            })
        })
    </script>
{% endblock %}

验证码图片的点击更换:

给图片<img src="{% url 'image_code' %}" id="imageCode" title="点击更换图片" alt="">设置id,平且给此id添加点击事件。

{% block js %}
    <script>
        $(function () {
            // 找到id为imageCode,添加点击事件
            $('#imageCode').click(function () {
                // 定义变量oldSrc,拿到当前id的src属性的值(图片地址)
                var oldSrc = $(this).attr('src');
                // 每点击一次就将当前id所在的src的值加一个?(用来替换图片)
                // oldSrc ->  oldSrc? -> oldSrc?? -> ...
                $(this).attr('src', oldSrc + '?');
            })
        })
    </script>
{% endblock %}

登录

def login(request):
    """用户名密码登录"""
    if request.method == 'GET':
        form = LoginForm(request)
        return render(request, 'login.html', {'form': form})
    
    form = LoginForm(request, data=request.POST)
    if form.is_valid():
        # 获取数据时写的name为username,实际上获取的是手机号或者邮箱
        username = form.cleaned_data['username']  
        password = form.cleaned_data['password']

        # user_obj = models.User.objects.filter(username=username, password=password).first()
        # 使用Q对象构造复杂的查询对象(判断是用email还是phone登录的)
        user_obj = models.User.objects.filter(Q(email=username) | Q(phone=username)).filter(password=password).first()

        if user_obj:
            # 如果此用户存在,那么将用户的id保存在session中
            request.session['user_id'] = user_obj.pk
            request.session.set_expiry(60*60*24*14)
            return redirect('index')
        # 若不存在此用户,则抛出错误提示
        form.add_error('username', '用户名或密码有误')
    return render(request, 'login.html', {'form': form})

本文地址:https://blog.csdn.net/weixin_43670190/article/details/111964614

相关标签: Django python