如果使用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
说点什么
欢迎讨论