• 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')

  • 相关阅读:
    cp备份操作时如何忽略指定的目录
    Wordpress“固定链接”页面出现404原因及解决方法
    CentOS7上搭建WEB服务器
    坑爹的云服务安全组
    java spring hibernate
    电脑性能
    android subclipse subversive
    android 开发 程序中下载安装APK文件 问题汇总 解析程序包时出现问题
    android sqlite datetime demo
    android SurfaceView中播放视频 按视频的原始比例播放
  • 原文地址:https://www.cnblogs.com/huiyichanmian/p/12219858.html
Copyright © 2020-2023  润新知