9-Django项目--验证码操作

目录

templates/login/login.html

utils/code.py

views/login.py

验证码

生成验证码

code.py

应用验证码

views.py

login.html


templates/login/login.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap.css'%}">
</head>
<body>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        html {
            height: 100%;
        }
        body {
            height: 100%;
        }
        .container {
            height: 100%;
            width: 100%;
            background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
        }
        .login-wrapper {
            background-color: #fff;
            width: 358px;
            height: 588px;
            border-radius: 15px;
            padding: 0 50px;
            position: relative;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        .header {
            font-size: 38px;
            font-weight: bold;
            text-align: center;
            line-height: 200px;
        }
        .input-item {
            display: block;
            width: 100%;
            margin-bottom: 20px;
            border: 0;
            padding: 10px;
            border-bottom: 1px solid rgb(128, 125, 125);
            font-size: 15px;
            outline: none;
        }
        .input-item:placeholder {
            text-transform: uppercase;
        }
        .btn {
            text-align: center;
            padding: 10px;
            width: 100%;
            margin-top: 40px;
            background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
            color: #fff;
        }
        .msg {
            text-align: center;
            line-height: 88px;
        }
        a {
            text-decoration-line: none;
            color: #abc1ee;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="login-wrapper">
            <div class="header">Login</div>
            <div class="form-wrapper">
                <form method="post" novalidate>
                    {% csrf_token %}
                    <div class="col-md-12">
                        {{ form.username }}
                        <span style="color: red">{{ form.password.errors.0 }}</span>
                        {{ form.password }}
                    </div>
                    <div class="col-md-7">
                        {{ form.code }}
                        <span style="color:red;">{{ form.code.errors.0 }}</span>
                    </div>
                    <div class="col-md-5">
                        <button style="border: none">
                            <img src="/image/code/">
                        </button>

                    </div>

                    <button class="btn" type="submit">Login</button>
                </form>
            </div>

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

</body>
</html>

utils/code.py

# -*- coding:utf-8 -*-
# pip install pillow==9.4.0

from PIL import Image, ImageFont, ImageDraw
from random import choice,randint

def create_image_content():
    # 创建一张图片
    img = Image.new(mode="RGB", size=(110, 40), color=(255, 255, 255))
    # 创建一个画笔
    draw = ImageDraw.Draw(img, mode="RGB")
    font = ImageFont.truetype("./simkai.ttf", size=30)

    # 验证码出现的字符
    text = "ABCDEFG23456789"

    # 存放四位验证码的字符串
    image_text = ""
    # 生成几位数的验证码,就循环几次
    for num in range(4):
        image_text += choice(text)

    # 每次遍历的时候,将字符添加到图片上
    x = 15
    for i in image_text:
        # 为每一位验证码添加不同颜色
        R = str(randint(0, 255))
        G = str(randint(0, 255))
        B = str(randint(0, 255))
        draw.text(
            (x, 5),
            text=i,
            font=font,
            fill=f"rgb({R},{G},{B})"
        )
        x += 20

    # 添加干扰线条
    for i in range(1, randint(3, 6)):
        x1, y1 = randint(0, 110), randint(0, 40)
        x2, y2 = randint(0, 110), randint(0, 40)
        R = str(randint(0, 255))
        G = str(randint(0, 255))
        B = str(randint(0, 255))
        draw.line((x1, y1, x2, y2),fill=f"rgb({R},{G},{B})", width=2)

    # 添加干扰点
    for i in range(1, randint(30, 50)):
        x1, y1 = randint(0, 110), randint(0, 40)
        R = str(randint(0, 255))
        G = str(randint(0, 255))
        B = str(randint(0, 255))
        draw.point([x1, y1], fill=f"rgb({R},{G},{B})")

    # print(image_text)
    # img.save("code.png")
    # print(img)
    return [img, image_text]



views/login.py

# -*- coding:utf-8 -*-
from django.shortcuts import render, redirect,HttpResponse
from demo_one.utils import pwd_data
from django import forms
from demo_one import models
from demo_one.utils.code import create_image_content


class LoginForm(forms.Form):
    username = forms.CharField(label="用户名", widget=forms.TextInput(
        attrs={"class": "input-item", "autocomplete": "off", "placeholder": "请输入用户名"}))
    password = forms.CharField(label="密码", widget=forms.PasswordInput(
        attrs={"class": "input-item", "autocomplete": "off", "placeholder": "请输入密码"}))
    code = forms.CharField(label="验证码", widget=forms.TextInput(
        attrs={"class": "input-item", "autocomplete": "off", "placeholder": "请输入验证码"}))


    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        # print(self.cleaned_data)
        return pwd_data.md5(pwd)


def login(request):
    if request.method == "GET":
        form = LoginForm()
        return render(request, "login/login.html", {"form": form})

    form = LoginForm(data=request.POST)
    if form.is_valid():
        # 去数据库进行校验
        # print(form.cleaned_data)
        # 使用pop删除,pop返回被删除的值
        user_input_code = form.cleaned_data.pop("code")
        code = str(request.session.get("image_code"))
        # print("我自己输入的是:", user_input_code)
        # print("系统生成的是:", code)
        if user_input_code.upper() != code.upper():
            form.add_error("code", "验证码错误")
            return render(request, "login/login.html", {"form": form})
        admin_object = models.Adminrole.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            # 给输入框添加一个错误提示
            form.add_error("password", "用户名或密码错误")
            return render(request, "login/login.html", {"form": form})
        # 登录成功之后
        # 将登录信息存储在session当中
        request.session["info"] = {"id": admin_object.id, "username": admin_object.username,
                                   "password": admin_object.password, "role": admin_object.role}
        # 时效性
        request.session.set_expiry(60 * 60 * 24 * 30)
        # 登录成功后跳转到首页
        return redirect("/")
    return render(request, "login/login.html", {"form": form})


def logout(request):
    request.session.clear()
    return redirect("/login/")


from io import BytesIO

def image_code(request):
    image, text = create_image_content()
    request.session["image_code"] = text
    request.session.set_expiry(60)

    stream = BytesIO()
    image.save(stream, "png")
    return HttpResponse(stream.getvalue())

验证码

生成验证码

  • code.py

    # -*- coding:utf-8 -*-
    # pip install pillow==9.4.0
    ​
    from PIL import Image, ImageFont, ImageDraw
    from random import choice,randint
    ​
    def create_image_content():
        # 创建一张图片
        img = Image.new(mode="RGB", size=(110, 40), color=(255, 255, 255))
        # 创建一个画笔
        draw = ImageDraw.Draw(img, mode="RGB")
        font = ImageFont.truetype("./simkai.ttf", size=30)
    ​
        # 验证码出现的字符
        text = "ABCDEFG23456789"
    ​
        # 存放四位验证码的字符串
        image_text = ""
        # 生成几位数的验证码,就循环几次
        for num in range(4):
            image_text += choice(text)
    ​
        # 每次遍历的时候,将字符添加到图片上
        x = 15
        for i in image_text:
            # 为每一位验证码添加不同颜色
            R = str(randint(0, 255))
            G = str(randint(0, 255))
            B = str(randint(0, 255))
            draw.text(
                (x, 5),
                text=i,
                font=font,
                fill=f"rgb({R},{G},{B})"
            )
            x += 20
    ​
        # 添加干扰线条
        for i in range(1, randint(3, 6)):
            x1, y1 = randint(0, 110), randint(0, 40)
            x2, y2 = randint(0, 110), randint(0, 40)
            R = str(randint(0, 255))
            G = str(randint(0, 255))
            B = str(randint(0, 255))
            draw.line((x1, y1, x2, y2),fill=f"rgb({R},{G},{B})", width=2)
    ​
        # 添加干扰点
        for i in range(1, randint(30, 50)):
            x1, y1 = randint(0, 110), randint(0, 40)
            R = str(randint(0, 255))
            G = str(randint(0, 255))
            B = str(randint(0, 255))
            draw.point([x1, y1], fill=f"rgb({R},{G},{B})")
    ​
        # print(image_text)
        # img.save("code.png")
        # print(img)
        return [img, image_text]

应用验证码

  • views.py

    def login(request):
        if request.method == "GET":
            form = LoginForm()
            return render(request, "login/login.html", {"form": form})
    ​
        form = LoginForm(data=request.POST)
        if form.is_valid():
            # 去数据库进行校验
            # print(form.cleaned_data)
            # 使用pop删除,pop返回被删除的值
            user_input_code = form.cleaned_data.pop("code")
            code = str(request.session.get("image_code"))
            # print("我自己输入的是:", user_input_code)
            # print("系统生成的是:", code)
            if user_input_code.upper() != code.upper():
                form.add_error("code", "验证码错误")
                return render(request, "login/login.html", {"form": form})
            admin_object = models.Adminrole.objects.filter(**form.cleaned_data).first()
            if not admin_object:
                # 给输入框添加一个错误提示
                form.add_error("password", "用户名或密码错误")
                return render(request, "login/login.html", {"form": form})
            # 登录成功之后
            # 将登录信息存储在session当中
            request.session["info"] = {"id": admin_object.id, "username": admin_object.username,
                                       "password": admin_object.password, "role": admin_object.role}
            # 时效性
            request.session.set_expiry(60 * 60 * 24 * 30)
            # 登录成功后跳转到首页
            return redirect("/")
        return render(request, "login/login.html", {"form": form})
    ​
    ​
    def logout(request):
        request.session.clear()
        return redirect("/login/")
    ​
    ​
    from io import BytesIO
    ​
    def image_code(request):
        image, text = create_image_content()
        request.session["image_code"] = text
        request.session.set_expiry(60)
    ​
        stream = BytesIO()
        image.save(stream, "png")
        return HttpResponse(stream.getvalue())

login.html

  • login.html
    
    {% load static %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'css/bootstrap.css'%}">
    </head>
    <body>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            html {
                height: 100%;
            }
            body {
                height: 100%;
            }
            .container {
                height: 100%;
                width: 100%;
                background-image: linear-gradient(to right, #fbc2eb, #a6c1ee);
            }
            .login-wrapper {
                background-color: #fff;
                width: 358px;
                height: 588px;
                border-radius: 15px;
                padding: 0 50px;
                position: relative;
                left: 50%;
                top: 50%;
                transform: translate(-50%, -50%);
            }
            .header {
                font-size: 38px;
                font-weight: bold;
                text-align: center;
                line-height: 200px;
            }
            .input-item {
                display: block;
                width: 100%;
                margin-bottom: 20px;
                border: 0;
                padding: 10px;
                border-bottom: 1px solid rgb(128, 125, 125);
                font-size: 15px;
                outline: none;
            }
            .input-item:placeholder {
                text-transform: uppercase;
            }
            .btn {
                text-align: center;
                padding: 10px;
                width: 100%;
                margin-top: 40px;
                background-image: linear-gradient(to right, #a6c1ee, #fbc2eb);
                color: #fff;
            }
            .msg {
                text-align: center;
                line-height: 88px;
            }
            a {
                text-decoration-line: none;
                color: #abc1ee;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="login-wrapper">
                <div class="header">Login</div>
                <div class="form-wrapper">
                    <form method="post" novalidate>
                        {% csrf_token %}
                        <div class="col-md-12">
                            {{ form.username }}
                            <span style="color: red">{{ form.password.errors.0 }}</span>
                            {{ form.password }}
                        </div>
                        <div class="col-md-7">
                            {{ form.code }}
                            <span style="color:red;">{{ form.code.errors.0 }}</span>
                        </div>
                        <div class="col-md-5">
                            <button style="border: none">
                                <img src="/image/code/">
                            </button>
    ​
                        </div>
    ​
                        <button class="btn" type="submit">Login</button>
                    </form>
                </div>
    ​
            </div>
        </div>
    </body>
    </html>
    ​
    </body>
    </html>

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值