Django中的分页器以及手绘验证码

Posted huiyichanmian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django中的分页器以及手绘验证码相关的知识,希望对你有一定的参考价值。

一、分页器

1、分页器的好处

通过分页管理多条数据,可以美化界面并能提高查询效率

2、一般方式进行分页

def get_students(request):

    page = int(request.GET.get("page", 1))  # 获取页码

    per_page = int(request.GET.get("per_page", 10))  # 获取每页需要显示的数量

    students = Student.objects.all()[per_page*(page-1): page * per_page]   # 进行分页查询

    data = {
        "students": students
    }

    return render(request, students.html, context=data)

3、使用分页器

from django.core.paginator import Paginator

3.1、分页器对象

(1)、实例化分页器对象
paginator = Paginator(数据源,每页最多显示的条数)
(2)、属性

count 对象总数

num_pages 页面总数

page_range 页码列表,从1开始

(3)、方法

page(page_num) 返回一个page对象,page_num为页码(整数)

3.2、页面对象

具体的某一页,由分页器的Page方法获得。

(1)、属性和方法

page_num 当前页码

object_list 当前页的数据

has_next 是否有下一页

has_previous 是否有上一页

next_page_number 下一页页码

previous_page_number 上一页页码

len() 当前页数据的个数

4、常见错误

(1)、InvalidPage

  page()传递无效页码

(2)、PageNotAnInteger

  page()传递的不是整数

(3)、Empty

  page()传递的值有效,但是没有数据

5、实例

(1)、url

from django.urls import path

from myapp.views import show_students

app_name = myapp

urlpatterns = [
    path(showstu/<pagenum>/,show_students,name=students),
]

(2)、view

from django.core.paginator import Paginator
from django.shortcuts import render

from myapp.models import Student

page_size = 3 #每页最多显示的条数

def show_students(request,pagenum):  #pagenum是页码参数
    students = Student.objects.all() #查询所有学生,返回QuerySet
    paginator = Paginator(students,page_size)  #实例化‘分页器对象‘,传入容器和page_size
    page = paginator.page(pagenum) #通过分页器对象返回Page,Page对象封装了某一页信息
    page_range = paginator.page_range  # 页码列表
    return render(request,students.html,locals())

(3)、html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学生信息</title>
</head>
<body>
    <table align="center" border="1">
        <tr>
            <th>学号</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>成绩</th>
        </tr>
        {% for student in page %}
            <tr>
                <td>{{ student.id }}</td>
                <td>{{ student.name }}</td>
                <td>{{ student.age }}</td>
                <td>{{ student.score }}</td>
            </tr>
        {% endfor %}

    </table>
    <center>
        <a href="{% url ‘myapp:students‘ 1 %}">首页</a>
        {% if page.has_previous %}
            <a href="{% url ‘myapp:students‘ page.previous_page_number %}">上一页</a>
            {% else %}
            <a href="javascript:alert(‘已经是首页了‘)">上一页</a>
        {% endif %}
        {% if page.has_next %}
            <a href="{% url ‘myapp:students‘ page.next_page_number %}">下一页</a>
        {% else %}
            <a href="javascript:alert(‘已经是末页了‘)">下一页</a>
        {% endif %}

        <a href="{% url ‘myapp:students‘ paginator.num_pages %}">末页</a>

    </center>
</body>
</html>

(4)、添加bootstrap样式

cdn:https://www.bootcdn.cn/

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/1.2.3/jquery.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.0/css/bootstrap.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.0/js/bootstrap.js"></script>
</head>
<body>
<table align="center" border="1">
    <tr>
        <th>学号</th>
        <th>姓名</th>
        <th>成绩</th>
    </tr>
    {% for student in page.object_list %}
        <tr>
            <td>{{ student.id }}</td>
            <td>{{ student.name }}</td>
            <td>{{ student.score }}</td>
        </tr>
    {% endfor %}

</table>
<center>
    <nav aria-label="Page navigation">
        <ul class="pagination">
            {% if page.has_previous %}
            <li>
                <a href="{% url ‘myapp:students‘ page.previous_page_number %}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
                </li>
                {% else %}

                <li class="disabled">
                <a href="#" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>
            {% endif %}

        {% for page_index in page_range %}
            {% ifequal page_index page.number %}
                <li class="active"><a href="{% url ‘myapp:students‘ page_index %}">{{ page_index }}</a></li>
            {% else %}
                <li><a href="{% url ‘myapp:students‘ page_index %}">{{ page_index }}</a></li>
            {% endifequal %}

        {% endfor %}

        {% if page.has_next %}
            <li>
                <a href="{% url ‘myapp:students‘  page.next_page_number %}" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        {% else %}
            <li class="disabled">
                <a href="#" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        {% endif %}

        </ul>
    </nav>
</center>
</body>
</html>

技术图片

 

 

 二、图片验证码

防止其它人恶意注册或访问攻击

1、手动实现验证码

(1)pillow

画布Image

  需要模式 RGB

  尺寸 (width, height)

  背景色 (10,20,30)

画笔ImageDraw

  绑定画布

  模式:RGB和ARGB

  封装了绘制的方法:test 绘制文本

           point 绘制点

           line 画线

           arch  圆弧形

字体ImageFront 

   手动指定字体

(2)、绘制流程

指定可用背景颜色 

bg = (220, 220, 180)  #RGB颜色

初始化画布

image = Image.new(‘RGB’,(120,30),bg)

获取画布中画笔对象

draw = ImageDraw.Draw(image, RGB)

随机四位验证码并绘制

a、生成4位随机字符
def generate_code():
    source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"

    code = ""

    for i in range(4):
        code += random.choice(source)

    return code
b、创建字体
font = ImageFont.truetype(font=static/font/Fangz.ttf, size=25)
c、指定字体颜色
font_color = (random.randrange(255),
                      random.randrange(255),
                      random.randrange(255))
d、绘制内容
draw.text((x,y),’R’,font,fontcolor)
e、画干扰点
for i in range(10000):
    fill = (random.randrange(255),
              random.randrange(255),
              random.randrange(255))
    xy = (random.randrange(201), random.randrange(100))
    imagedraw.point(xy=xy, fill=fill)

最后生成图片或图片对象,并返回响应。

2、和用户体系绑定

验证码真实数据需要持久化

session

cookie

3、动态刷新

浏览器缓存,根据url比对,

添加随机数,让url每次都发生变更

<img width="120" height="100%" src="/user/verifycode"
         onclick="flushVerifyCode(this)"><br>


function flushVerifyCode(img) {
        img.src= /user/verifycode?tm=+Math.random();
}

4、实例

(1)、view

import random
from io import BytesIO
from PIL import Image, ImageFont
from PIL.ImageDraw import Draw, ImageDraw



def get_color():
    return random.randrange(256)


def generate_code():
    source = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"

    code = ""

    for i in range(4):
        code += random.choice(source)

    return code


def get_code(request):

    # 初始化画布,初始化画笔

    mode = "RGB"

    size = (200, 100)

    red = get_color()

    green = get_color()

    blue = get_color()

    color_bg = (red, green, blue)

    image = Image.new(mode=mode, size=size, color=color_bg)

    imagedraw = ImageDraw(image, mode=mode)

    imagefont = ImageFont.truetype(settings.FONT_PATH, 100)

    verify_code = generate_code()

    request.session[verify_code] = verify_code

    for i in range(4):
        fill = (get_color(), get_color(), get_color())
        imagedraw.text(xy=(50*i, 0), text=verify_code[i], font=imagefont, fill=fill)

    for i in range(10000):
        fill = (get_color(), get_color(), get_color())
        xy = (random.randrange(201), random.randrange(100))
        imagedraw.point(xy=xy, fill=fill)

    fp = BytesIO()

    image.save(fp, "png")

    return HttpResponse(fp.getvalue(), content_type="image/png")

(2)、html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>

    <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.11.1/jquery.js"></script>

</head>
<body>

<form action="{% url ‘myapp:login‘ %}" method="post">

    <span>用户名:</span> <input type="text" name="username" placeholder="精神精神">

    <br>
    <span>验证码:</span><input type="text" name="verify_code" placeholder="请输入下图中的验证码">
    <br>
    <img src="{% url ‘myapp:get_code‘ %}">
{#    <img src="#">#}
    <br>
    <button>精神一下</button>
</form>
</body>
</html>


<script>
    $(function () {
    $("img").click(function () {
        console.log("点到我了");
        $(this).attr("src", "/myapp/get_code/?t=" + Math.random());
    })
})
</script>

(3)、setting

FONT_PATH = os.path.join(BASE_DIR, static/fonts/ADOBEARABIC-BOLD.OTF)

技术图片

以上是关于Django中的分页器以及手绘验证码的主要内容,如果未能解决你的问题,请参考以下文章

Django 第八篇Django自带的分页器

013---Django的分页器

如何解决 JQgrid 中的分页器显示

django -----分页器组件

Django -- 11.组件_分页器

django 的分页器Paginator ,从django中导入类