Django实战【登陆页面】BootStrap、auth、Ajax、forms组件、session、PIL制作验证码

基于用户认证组件和Ajax实现用户登陆验证(图片验证码)

运用知识点:

  • BootStrap实现页面设计
  • auth认证组件登陆
  • Ajax异步提交局部刷新校验
  • forms组件制作提交单
  • session储存验证码内容
  • PIL图片制作工具制作验证码(制作躁点)

整个目录

这里写图片描述

stting 配置

# 因为自定义了 auth模块的 UserInfo表,所以django要设置默认表位置
AUTH_USER_MODEL = 'blog.UserInfo'

页面html

注意点:

  • {% csrf_token %} ajax必须传过去
  • label for=”for属性可以让该label标签点击后焦点到某个标签
  • 点击验证码后从新访问一次路径,获得新图片 $(this)[0].src+='?'
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>欢迎登陆</title>
    <link rel="stylesheet" href="/static/blog/bs/css/bootstrap.css">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">
            <form action="">
                {% csrf_token %}
                <div class="form-group">
                    <label for="user">用户名</label>
                    <input type="text" id="user" class="form-control">
                </div>
                <div class="form-group">
                    <label for="pwd">密码</label>
                    <input type="password" id="pwd" class="form-control">
                </div>

                <div class="form-group">
                    <label for="">验证码</label>
                    <div class="row">
                        <div class="col-md-6">
                            <input type="text" class="valid_code form-control">
                        </div>
                        <div class="col-md-6">
                            <img width="263" height="34" id='code_img' src="/get_validCode_img/" alt="">
                        </div>
                    </div>
                </div>
                {# 后面加span 错误提示 #}
                <input type="button" class="btn btn-default login_btn" value="登陆"><span class="error"></span>

            </form>


        </div>
    </div>

</div>
</body>
<script src="/static/blog/js/jquery-3.3.1.min.js"></script>
<script>
    //刷新验证码
    $('#code_img').click(function () {
        $(this)[0].src+='?'  //点击验证码后从新访问一次路径,获得新图片
    })

    // 登陆验证
    $('.login_btn').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:{
                user:$('#user').val(),
                pwd:$('#pwd').val(),
                valid_code:$('.valid_code').val(),
                csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()  //token值
            },
            success:function (data) {
                console.log(data)
                if (data.user){
                    location.href='/index/'  //js 跳转页面
                }
                else{
                    $('.error').text(data.msg).css({'color':'red', 'margin-left':'20px'})
                }
            }
        })

    })

</script>
</html>

验证码模块制作

注意点:

  • 这种类似的功能性模块,封装起来单独建立文件夹存放 utils
  • PIL制图模块的使用:内含制图、画线、画点、写字等
import random

def get_random_color():
    """
    生产随机 颜色
    :return:
    """
    color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
    return color


def get_valid_code_img(request):
    """
    生产随机验证码图片
    :param request:
    :return:
    """
    # 图片生成模块  pip3 install pillow
    from PIL import Image
    # 画板工具
    from PIL import ImageDraw
    # 图片字体模块
    from PIL import ImageFont
    # 内存管理工具
    from io import BytesIO

    # 生成图片
    width = 270
    height = 40
    img = Image.new('RGB', (width, height), color=get_random_color())
    # 画板工具 写入文字
    draw = ImageDraw.Draw(img)
    # 字体设置
    set_font = ImageFont.truetype('static/blog/font/AaMangXiaoGuo-2.ttf', size=24)
    # 制作随机字符5位
    valid_code_str = ''  # 验证码字符串
    for i in range(5):
        random_num = str(random.randint(0, 9))  # 随机数字
        random_low_alpha = chr(random.randint(95, 122))  # 随机小写
        random_upper_alpha = chr(random.randint(65, 90))  # 随机大写
        # 随机选择一个
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        # 写入字
        draw.text((i*50+20, 5), random_char, get_random_color(), font=set_font)  # 参数:位置,内容,颜色,字体
        # 保存验证码字符串,用来比对用户输入
        valid_code_str += random_char

    # 制作噪点,直线和点
    for i in range(3):
        x1 = random.randint(0, width)
        x2 = random.randint(0, width)
        y1 = random.randint(0, height)
        y2 = random.randint(0, height)
        draw.line((x1, y1, x2, y2), fill=get_random_color())  # 画线

    for i in range(10):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=get_random_color())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x+4, y+4), 0, 90, fill=get_random_color())

    # 储存验证码值到Session中(便于分离各个用户)
    request.session['valid_code_str'] = valid_code_str
    f = BytesIO()  # 内存具柄
    img.save(f, 'png')
    data = f.getvalue()

    return data

视图views

注意点:

  • 验证码生成结果储存到 session中,避免多用户之间混淆
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from django.contrib import auth


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    else:
        # Json 返回登陆结果
        response = {'user': None, 'msg': None}
        # 提交的登陆post
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        valid_code = request.POST.get('valid_code')  # 图片验证码

        # 获取到session中的验证码值
        valid_code_str = request.session.get('valid_code_str')

        if valid_code.upper() == valid_code_str.upper():  # 不区分大小写
            # 进行账号认证
            user = auth.authenticate(username=user, password=pwd)
            if user:  # 有这个用户
                auth.login(request, user)  # request.user == 当前登陆对象
                response['user'] = user.username
            else:
                response['msg'] = '用户名或密码错误!'

        else:
            response['msg'] = '验证码错误'

        return JsonResponse(response)


def get_validCode_img(request):
    """
    给予PIL模块动态生产验证码
    :param request:
    :return:
    """
    from blog.utils.validCode import get_valid_code_img  # 导入自己创建的工具文件utils
    data = get_valid_code_img(request)
    return HttpResponse(data)


def index(request):

    return render(request, 'index.html')

猜你喜欢

转载自blog.csdn.net/weixin_42329277/article/details/81976250