django+angular-datatable的分页实现

如果使用django本身的模板引擎,实现前后端分页是很简单的,也有很多django的库可以使用:参考:How to Paginate with Django

文章最后也会附上使用skipppage的方式,下面只介绍和datatable插件结合时如何实现分页效果。

datatable本来是jquery的插件,用的人很多,angular-datatable是他的一种自定义实现,前端结合bootstrap或者matrial样式,可以快速实现分页,而后端的分页,需要结合datatable发出的字段,再进行后端逻辑的实现。

angular-datatable的官方文档:文档

前端JS代码:

var vm = this;
vm.edit = edit;
vm.dblClickHandler = dblClickHandler;
vm.dtInstance = {};
vm.dtOptions = DTOptionsBuilder.newOptions()
        .withOption('ajax', {
            url: '/api/machines/get_all/',
            type: 'POST'
        })
        .withDataProp('data')
        .withOption('serverSide', true)
        .withPaginationType('full_numbers')
        .withOption('createdRow', createdRow)
        .withOption('rowCallback', rowCallback);
vm.dtColumns = [
        DTColumnBuilder.newColumn('serial'),
        DTColumnBuilder.newColumn('ci'),
        DTColumnBuilder.newColumn('ip'),
        DTColumnBuilder.newColumn('env'),
        DTColumnBuilder.newColumn('subenv'),
        DTColumnBuilder.newColumn('cpu'),
        DTColumnBuilder.newColumn('mem'),
        DTColumnBuilder.newColumn('disk'),
        DTColumnBuilder.newColumn('os'),
//        DTColumnBuilder.newColumn('dsc'),
        DTColumnBuilder.newColumn('pd'),
        DTColumnBuilder.newColumn(null).renderWith(vm_status),
        DTColumnBuilder.newColumn(null).renderWith(cloud_status),
        DTColumnBuilder.newColumn('machine_type'),
        DTColumnBuilder.newColumn(null).renderWith(actionsHtml).withClass("vm_admin")
    ];

 // 双击弹出详情的回调
    function rowCallback(nRow, aData) {
        $('td', nRow).unbind('dblclick');
        $('td', nRow).bind('dblclick', function () {
            $scope.$apply(function () {
                vm.dblClickHandler(aData.ci, aData.ip, aData.join_tars, aData.dsc);
            });
        });
        return nRow;
    }

    function dblClickHandler(ci, ip, tars, dsc) {
        var modalInstance = $modal.open({
            templateUrl: 'static/contents/others/cmdb_modal.html',
            controller: 'cmdb_modalController',
            resolve: {
                ci: function () {
                    return ci;
                },
                ip: function () {
                    return ip;
                },
                tars: function () {
                    return tars;
                },
                dsc: function () {
                    return dsc;
                }
            }
        });
    }

    function createdRow(row, data, dataIndex) {
        $compile(angular.element(row).contents())($scope);
    }

前端html代码:

<table datatable="" dt-options="vm.dtOptions" dt-columns="vm.dtColumns"
                               dt-instance="vm.dtInstance" class="table table-bordered  table-hover">
                            <thead>
                            <tr>
                                <th>ID</th>
                                <th>Name</th>
                                <th>IP</th>
                                <th>Env</th>
                                <th>Subenv</th>
                                <th>CPU</th>
                                <th>Mem(GB)</th>
                                <th>Disk(GB)</th>
                                <th>OS</th>
                                <!--<th width="10%">Description</th>-->
                                <th>PD</th>
                                <th>使用状态</th>
                                <th>运行状态</th>
                                <th>机器类型</th>
                                <th width="13%">Actions</th>
                            </tr>
                            </thead>
                        </table>

后端python代码:

@login_required
def get_all_machineInfo(request):
    try:
        cols = {0: 'serial', 1: 'ci', 2: 'ip', 3: 'env', 4: 'subenv', 5: 'cpu', 6: 'mem', 7: 'disk', 8: 'os', 9: 'dsc',
                10: 'pd', 11: 'status', 12: 'machine_type'}
        draw = request.POST["draw"]
        start = int(request.POST["start"])
        length = int(request.POST["length"])
        order = int(request.POST["order[0][column]"])
        dir = request.POST["order[0][dir]"]
        search = request.POST["search[value]"]
        result = []
        order_by = cols.get(order) if dir == 'desc' else '-' + cols.get(order)
        if search:
            *********
        response = {
            "draw": draw,
            "recordsFiltered": sum,
            "recordsTotal": sum,
            "data": result
        }
        return HttpResponse(json.dumps(response), content_type='application/json')
    except:
        response = {
            "draw": 0,
            "recordsFiltered": 10,
            "recordsTotal": 10,
            "data": []
        }
        import logging

        logger = logging.getLogger(__name__)
        logger.error(traceback.format_exc())
        traceback.print_exc()
        return HttpResponse(json.dumps(response), content_type='application/json')

完成。

如果是django模板本身的方式:

可以使用:

前端代码:

<div id="js-grid-juicy-projects" class="cbp">
            {% for book in books %}
                <div class="cbp-item web-design logos">
                    <div class="cbp-caption">
                        <div class="cbp-caption-defaultWrap">
                            <img class="book_img" src="{{ book.detail.images.large }}" alt="">
                        </div>
                        <div class="cbp-caption-activeWrap">
                            <div class="cbp-l-caption-alignCenter">
                                <div class="cbp-l-caption-body">
                                    <a href="ajax-juicy-projects/project2.html"
                                       class="cbp-singlePage cbp-l-caption-buttonLeft"
                                       rel="nofollow">more info</a>
                                    <a href="http://scriptpie.com/cubeportfolio/img/?i=1200x900/efc6c0"
                                       class="cbp-lightbox cbp-l-caption-buttonRight"
                                       data-title="World Clock Widget<br>by Paul Flavius Nechita">view larger</a>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="cbp-l-grid-projects-title">{{ book.name }}</div>
                    <div class="cbp-l-grid-projects-desc">{{ book.detail.author.0 }}/{{ book.detail.pubdate }}/{{ book.detail.price }}/{{ book.detail.rating.average }}分</div>
                </div>
            {% endfor %}
        </div>
        <div class="pagination">
            <ul>
                {% if books.has_previous %}
                    <li><a href="/douban/index/?page={{ books.previous_page_number }}">«</a></li>
                {% else %}
                    <li class="disabled"><span>«</span></li>
                {% endif %}

                {% for page in pages_to_show %}
                    {% if page == -1 %}
                        <li class="disabled"><a href="/douban/index/?page={{ page }}">…</a></li>
                    {% elif page == books.number %}
                        <li class="active"><a href="/douban/index/?page={{ page }}">{{ page }}</a></li>
                    {% else %}
                        <li><a href="/douban/index/?page={{ page }}">{{ page }}</a>
                    {% endif %}
                {% endfor %}

                {% if books.has_next %}
                    <li><a href="/douban/index/?page={{ books.next_page_number }}">»</a></li>
                {% else %}
                    <li class="disabled"><a href="/douban/index/?page={{ page }}">»</a></li>
                {% endif %}

            </ul>
        </div>

后端代码:

def index(request):
    page = int(request.GET.get('page', 1))
    all_books = Book.objects.all().order_by("id")
    p = SkippingPages(all_books, 10)
    try:
        pages_to_show = p.pages_to_show(page)
        books = p.pages.page(page)
        for i in books:
            if not i.detail:
                books.remove(i)
    except PageNotAnInteger:
        books = p.pages.page(1)
        pages_to_show = p.pages_to_show(1)
    except EmptyPage:
        books = p.pages.page(p.pages.num_pages)
        pages_to_show = p.pages_to_show(p.pages.num_pages)
    return render(request, 'douban/books/book_list.html', {'books': books, "pages_to_show": pages_to_show})

# -*- coding: utf-8 -*-
from django.core.paginator import Paginator


class SkippingPages:
    def __init__(self, objects, count):
        self.pages = Paginator(objects, count)

    def pages_to_show(self, page):
        # pages_wanted stores the pages we want to see, e.g.
        # - first and second page always
        # - two pages before selected page
        # - the selected page
        # - two pages after selected page
        # - last two pages always
        #
        # Turning the pages into a set removes duplicates for edge
        # cases where the "context pages" (before and after the
        # selected) overlap with the "always show" pages.
        pages_wanted = set([1, 2,
                            page - 2, page - 1,
                            page,
                            page + 1, page + 2,
                            self.pages.num_pages - 1, self.pages.num_pages])

        # The intersection with the page_range trims off the invalid
        # pages outside the total number of pages we actually have.
        # Note that includes invalid negative and >page_range "context
        # pages" which we added above.
        pages_to_show = set(self.pages.page_range).intersection(pages_wanted)
        pages_to_show = sorted(pages_to_show)

        # skip_pages will keep a list of page numbers from
        # pages_to_show that should have a skip-marker inserted
        # after them.  For flexibility this is done by looking for
        # anywhere in the list that doesn't increment by 1 over the
        # last entry.
        skip_pages = [x[1] for x in zip(pages_to_show[:-1],
                                        pages_to_show[1:])
                      if (x[1] - x[0] != 1)]

        # Each page in skip_pages should be follwed by a skip-marker
        # sentinel (e.g. -1).
        for i in skip_pages:
            pages_to_show.insert(pages_to_show.index(i), -1)

        return pages_to_show

Written by

说点什么

欢迎讨论

avatar

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  Subscribe  
提醒