zoukankan      html  css  js  c++  java
  • Django分页

    分页的原理

    Django是一个非常全面的Web框架,也预置了分页的功能,这点稍后介绍。然而,我并不想按照Django给的分页功能来做。学习一个东西最好学习它的本质。分页的原理其实很简单,就是根据你传入的参数从数据库获取一部分的数据来展示。比如按照5篇文章来分页,每次就从数据库取5条数据,然后返回给前端展示即可。

    手动分页

    models的配置,并且一经使用了makemigrations和migrate同步了数据库中的表

    class Host(models.Model):
        name = models.CharField(max_length=10)
        ip = models.GenericIPAddressField()
    
        def __str__(self):
            return self.name
    models

    view的设置

    def batch(request, page):
        page = transfer2int(page, 1)
        count = Host.objects.count()
    
        per_item = transfer2int(request.COOKIES.get("pageNum", 30), 30)
        print("每页的大小", per_item)
    
        # 总页数
        page_num = math.ceil(count/per_item)
    
        if page > page_num:
            page = page_num
        elif page <= 0:
            page = 1
    
        # 本页的开始
        start = (page - 1) * per_item
        end = min(page * per_item, count)
    
        hosts = Host.objects.all()[start:end]
        print("page", page)
        print(hosts)
        if page_num <= 11:
            startIndex = 1
            endIndex = page_num
        else:
            if page <6:
                startIndex = 1
                endIndex = 11
            elif page + 5 > page_num:
                endIndex = page_num
                startIndex = page_num - 10
            else:
                startIndex = page - 5
                endIndex = page + 5
        return render(request, "batch.html", {"hosts": hosts,
                                              "count": count,
                                              "bars": range(startIndex, endIndex+1),
                                              "page_num": page_num,
                                              "page": page}
    view的配置
    page是从url出接收到的页码,也就是第几页,函数transfer2int是为了将字符串page转成数值型
    def transfer2int(arg, default):
        try:
            result = int(arg)
        except ValueError as e:
            result = default
        return result
    transfer2int
    count是表中的总记录数
    per_item是每页有多少条记录
    page_num是总页数
    hosts 是查询好的数据记录信息

    为了页面显示友好,也可以展示 页码条,当前是总共展示11个选择


    页面配置信息
    {% load staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>分页</title>
        <script type="text/javascript" src="{% static 'js/jquery-3.1.1.js' %}"></script>
        <script type="text/javascript" src="{% static 'js/jquery.cookie.js' %}"></script>
        <style type="text/css">
            table, td{
                border: solid 1px blueviolet;
            }
            #paging a{
                background-color: green;
                border: white solid 1px;
                text-decoration: none;
                color: white;
            }
            #paging a.selected{
                color: red;
            }
        </style>
    </head>
    <body>
    <table>
        <tr>
            <td>主机名</td>
            <td>IP</td>
        </tr>
        {% for host in hosts %}
            <tr>
                <td>{{ host.name }}</td>
                <td>{{ host.ip }}</td>
            </tr>
        {% endfor %}
    </table>
    <div>总条数{{ count }}</div>
    <select id="pageNum" onchange="changePageNum();">
        <option value="10">10</option>
        <option value="20">20</option>
        <option value="30">30</option>
        <option value="50">50</option>
        <option value="100">100</option>
    </select>
    <div id="paging">
        {% if page_num == 1 %}
            <a href="/shop/batch/1/">1</a>
        {% else %}
            {% if page > 1 %}
                <a href="/shop/batch/1/">首页</a>
            {% endif %}
            {% if page >= 2 %}
                <a href="/shop/batch/{{ page|add:-1 }}/">上一页</a>
            {% endif %}
            {% for bar in bars %}
                {% if page == bar %}
                    <a href="/shop/batch/{{ bar }}/" class="selected">{{ bar }}</a>
                {% else %}
                    <a href="/shop/batch/{{ bar }}/">{{ bar }}</a>
                {% endif %}
            {% endfor %}
            {% if page < page_num %}
                <a href="/shop/batch/{{ page|add:1 }}/">下一页</a>
                <a href="/shop/batch/{{ page_num }}/">尾页</a>
            {% endif %}
        {% endif %}
    </div>
    
    <script type="text/javascript">
        var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
        $(function () {
            var pageNum = $.cookie("pageNum");
            if (pageNum>0){
                $("#pageNum").val(pageNum);
            } else {
                $("#pageNum").val(30);
            }
        });
    </script>
    </body>
    </html>
    template
    原来我使用了ajax,在本例中没有使用。ajax在下篇随笔中会说明。

    Django分页

    django分页的关键使用了

    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

    关键是view中的编写
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    def batch2(request):
        page = transfer2int(request.GET.get('page'), 1)
        count = Host.objects.count()
    
        per_item = 10
        print("每页的大小", per_item)
    
        all_host = Host.objects.all()
        paginator = Paginator(all_host, per_item)  # Show 25 contacts per page
        try:
            hosts = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            hosts = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            hosts = paginator.page(paginator.num_pages)
    
        return render(request, "batch2.html", {"hosts":hosts})
    View Code

    页面如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>django分页</title>
    </head>
    <body>
    
    {% for host in hosts %}
        {{ host.name }}<br>
    {% endfor %}
    
    <div class="pagination">
        <span class="step-links">
            {% if hosts.has_previous %}
                <a href="?page={{ hosts.previous_page_number }}">previous</a>
            {% endif %}
    
            <span class="current">
                Page {{ hosts.number }} of {{ hosts.paginator.num_pages }}.
            </span>
    
            {% if hosts.has_next %}
                <a href="?page={{ hosts.next_page_number }}">next</a>
            {% endif %}
        </span>
    </div>
    
    </body>
    </html>
    页面

    还有一个问题没有解决哦,因为肯定有朋友会问,如果一个列表有100000个item, 我们想要实现每页40个,那么,当将我们请求该列表时,paginator 在分页过程中,请求数据库是取40个,还是取100000啊!显然,paginator 是不可能取100000的啦。paginator 巧妙的利用了Django延迟获取数据的特性,因此,paginator 每次取数据都是只取每页的数据的(也就是上例中的40个),所以是不会有性能 影响 的哦。

    官方文档  https://docs.djangoproject.com/en/1.10/topics/pagination/

  • 相关阅读:
    vue-router 实践
    修改vue中<router-link>的默认样式
    JSON.parse() 与 JSON.stringify() 的区别
    JS 中的异步操作
    CSS3 box-sizing:border-box的好处
    element ui 栅格布局
    css overflow用法
    koa中间件机制
    canvas 入门
    前端面试题:淘宝首页用了多少种标签
  • 原文地址:https://www.cnblogs.com/yangshl/p/6383247.html
Copyright © 2011-2022 走看看