Django自定义分页功能的实现

前言:本文介绍在Django中如何通过前后端代码实现页面自定义分页功能,详细介绍实现原理,并附实现代码。

实现的功能:

1、根据页数,显示分页标签,并限制显示的分页标签最多10个

2、当前页标签颜色高亮,当页数标签多于10个时位于分页标签的中间处

3、实现上一页、下一页、首页、尾页标签功能

4、具有跳转到指定页面功能,按enter或者点击按钮跳转

5、每页显示的行数可定制,行数修改后页数也跟着变更,每页显示行数使用cookie来保存


实现的原理:

1、分页标签先在后台组装好(这里使用a标签),可以页数几个就组装几个分页标签,然后由Django插入到前端的HTML代码中统一发给请求端。

2、当前页标签高亮功能:首先需要知道用户当前页是哪,这从客户端发送过来的请求数据里取得,然后在组装当前页标签内容时,加上特殊的CSS样式,返回给用户,这样在前端看到的当前页标签样式就和其他不同。

3、当前页标签居中:我们这边限制最多只显示10个标签,后台组装页码标签,一般从(当前页码-4)到(当前页码+5)。特殊情况该功能不起作用,例如1、总页数小于等于10页;2、当前页小于5;3、当前页大于总页数-5。

4、每页显示的行数定制功能:首次请求,默认10行,保存在cookie中。点击修改行数自动触发事件,修改客户端中保存行数信息的cookie值,并刷新页面。服务端在收到客户端发送过来信息中,从cookie中取得行数定制信息,按该行数组装分页标签,再返回给前端。


用到的知识点:

后端

1、request.COOKIES.get(key):取得cookie值,设置cookie:HttpResponse/redirect/render().set_cookie.(k,v,...)

2、render(request, 'URL', {k,v}):返回给前端,可以带参数

3、locals():返回当前所有的本地变量字典,存在部分是django模板用不到变量

3、mark_safe:转义,将HTML代码给转换成HTML实体,否则Django插入前端显示的是“HTML代码”

前端

1、获取cookie:$.cookie(k),设置cookie:$.cookie(k,v,{'path':value})

2、刷新页面location.reload(),跳转到指定页面location.href=url

3、$('XX').bind('keypress', function (event){}):绑定事件band,键盘输入事件keypress,键盘输入值event.keyCode,13为enter

4、$('XX').change(function (){}):change有变动自动触发事件,这边用在修改页面显示行数

5、{{ xxx|safe }}:|,过滤器,safe,将HTML代码给转换成HTML实体,防止XXS攻击,功能后后端的mark_safe相同


后端代码:

def query(request):

"""

current_page:当前页码,默认第一页

line_num:每页显示的行数,默认10行

table_line_count:总行数

page_count:总页数

display_page_num_count:显示的页数码标签总个数,默认10个

"""

    current_page = int(request.GET.get('p',1))

    line_num = int(request.COOKIES.get("per_page_line_num",10))

    table_line_count=tablename.objects.count()            ####统计表总行数,tablename指数据库中的表,根据实际修改

display_page_num_count=10

    ####求总页数

    a,b=divmod(table_line_count,line_num)      ####求除数和余数,例如divmod(5,1)=(1,1)

    if b>0:

        page_count=a+1

    else:

        page_count = a

"""

first_page:首页

    last_page:尾页

    prev_page:上一页

    next_page:下一页

first_display_page_num:第一个显示的页码

last_display_page_num:最后一个显示的页码

"""

    first_page = "<a href='/query/?p=%s'>%s</a>" % (1, "首页")

    last_page = "<a href='/query/?p=%s'>%s</a>" % (page_count, "尾页")

    if current_page-1==0:

        prev_page="<a href='/query/?p=%s'>%s</a>" % (current_page, "上一页")

    else:

        prev_page="<a href='/query/?p=%s'>%s</a>" % (current_page-1, "上一页")

    if current_page==page_count:

        next_page="<a href='/query/?p=%s'>%s</a>" % (current_page, "下一页")

    else:

        next_page="<a href='/query/?p=%s'>%s</a>" % (current_page+1, "下一页")

    page_str=""

    page_str+=first_page

    page_str+=prev_page


    if page_count<=display_page_num_count:

        first_display_page_num = 1

        last_display_page_num = page_count + 1

    else:

        # 总页数大于10页(只显示10个页数标签)

        #    如果当前页数《=5

        #        显示1-10页数标签

        #    如果当前页数x》5

        #        显示 x-4到x+5页数标签

        #    如果当前页数x》总页数-5

        #        显示 总页数-9 到总页数之间的标签

        if current_page_num<=5:

            first_display_page_num=1

            last_display_page_num=display_page_num_count

        elif 5<current_page_num<=page_count-5:

            first_display_page_num=current_page_num-5+1

            last_display_page_num=current_page_num+5

        else:

            first_display_page_num=page_count-5-5+1

            last_display_page_num=page_count

    for i in range(first_display_page_num, last_display_page_num):

        if i == current_page:

            page_str += "<a class='active'  href='/query/?p=%s'>%s</a>" % (i, i)

        else:

            page_str += "<a href='/query/?p=%s'>%s</a>" % (i, i)

    page_str += next_page

    page_str += last_page

    page_str = mark_safe(page_str)

    response = render(request, 'query.html', locals())

    response.set_cookie("per_page_line_num",line_num,path='/query/')  ####设置每页显示的行数

    return response

前端代码(query.html)

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <title></title>

    <style>

        .pagination {

            display: inline-block;

            padding-left: 0;

            margin: 20px 0;

            border-radius: 4px;

        }

        .pagenumber {

            display: inline-block;

            padding-left: 0;

            margin: 20px 0;

            border-radius: 4px;

        }

        .pagenumber a {

            display: inline-block;

            padding: 5px;

            background-color: #9cc2cb;

        }

        .pagenumber a.active {

            background-color: brown;

            color: white;

        }

    </style>

</head>

<body>

<label>共{{page_count}}页,{{table_line_count}}行,每页显示

    <select class="pagination" id="per_page_line_num">

        <option>10</option>

        <option>30</option>

        <option>50</option>

        <option>100</option>

    </select>

    条记录,</label>

<label>前往

    <input type='text' style='width:36px'>页

    <input type='button' value='GO' onclick="jumpto(this,'/query/?p=')">

</label>

<div class="pagenumber">

    {{ page_str|safe }}

    <!--{{ page_str }}-->

</div>

<script>

    //设置页面显示的行数,每次访问都先从cookie中取得

    $(function () {

        var v = $.cookie('per_page_line_num');

        $('#per_page_line_num').val(v)

    });

    //修改页面显示行数

    $('#per_page_line_num').change(function () {

        var v = $('#per_page_line_num').val();

        $.cookie('per_page_line_num', v, {'path': '/query/'});

        console.log(v);

        location.reload();

    });

    //跳转到指定页面功能函数,鼠标点击按钮触发

    function jumpto(ths, url) {

        var v = $(ths).siblings().val();

        location.href = url + v;

    }

    //跳转到指定页面功能函数,enter触发

    //    $('label input[type=text]').keydown(function (event) {

    $('label input[type=text]').bind('keypress', function (event) {

        //  console.log($(this).val(), event.keyCode);

        if (event.keyCode == 13) {

            var v = $(this).val();

            var url = "/query/?p=";

            location.href = url + v;

        }

    });

</script>

</body>

</html>

是全页面刷新,且每页显示数量放在cookie里传给服务端,然后服务端再根据这信息编排页码标签返回给客户端。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容