1.分页:
分页使用Django内置的分页模块来实现
官方的分页案例
1 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 2 from django.shortcuts import render 3 #后端 4 def listing(request): 5 contact_list = Contacts.objects.all() 6 paginator = Paginator(contact_list, 25) # Show 25 contacts per page 7 8 page = request.GET.get('page') 9 try:10 contacts = paginator.page(page)11 except PageNotAnInteger:12 # If page is not an integer, deliver first page.13 contacts = paginator.page(1)14 except EmptyPage:15 # If page is out of range (e.g. 9999), deliver last page of results.16 contacts = paginator.page(paginator.num_pages)17 18 return render(request, 'list.html', { 'contacts': contacts})19 #前端20 % for contact in contacts %}21 { # Each "contact" is a Contact model object. #}22 { { contact.full_name|upper }}23 ...24 {% endfor %}25 #分页组件26
在项目中由于分页之前要进行条件筛选和排序,所以分页如下
1 from django.core.paginator import Paginator,EmptyPage, PageNotAnInteger
def table_filter(request,admin_class): '''进行条件过滤,并返回过滤后的数据和条件''' filter_condition = {} for k,v in request.GET.items(): if v: filter_condition[k]=v return admin_class.model.objects.filter(**filter_condition),filter_condition
1 def display_table_objs(request,app_name,table_name): 2 admin_class = king_admin.enabled_admins[app_name][table_name] 3 #有后端查询出结果集和条件,并对其进行分页操作 4 object_list,filter_conditions = table_filter(request,admin_class) 5 6 paginator = Paginator(object_list, admin_class.list_per_page) 7 page = request.GET.get('page') 8 try: 9 objects = paginator.page(page)10 except PageNotAnInteger:11 objects = paginator.page(1)12 except EmptyPage:13 objects = paginator.page(paginator.num_pages)14 15 return render(request,'king_admin/table_objs.html',{ 'admin_class':admin_class,16 'query_sets':objects,17 'filter_conditions':filter_conditions})
1 {% block container %} 2356 {% endblock %}46Panel title
57558 { # #} 9 2122 { # #}2324 25
40 { # #}41 5426 {% for column in admin_class.list_display %}27 30 31 32 { # #}33 {% for obj in query_sets %}34{ { column }} 28 {% endfor %}2935 {% bulid_table_row obj admin_class %}36 37 {% endfor %}38 39
自定义标签的tags的方法
1.导入
1 from django import template2 from django.utils.safestring import mark_safe3 register = template.Library()
2.动态加载表格 render_app_name
1 @register.simple_tag2 def render_app_name(admin_class):3 '''渲染动态获取表名'''4 return admin_class.model._meta.verbose_name_plural
3.动态展示表格中的数据 build_table_row
1 @register.simple_tag 2 def bulid_table_row(obj,admin_class): 3 '''生成数据内容的td,填充到table中,展示前端''' 4 row_ele = '' 5 for column in admin_class.list_display: 6 #获取每个字段的类型的对象 7 field_obj = obj._meta.get_field(column) 8 #判断是否是choice字段 9 if field_obj.choices:10 #如果是choice字段,则按照choice的值进行展示11 column_data = getattr(obj,"get_%s_display"%column)()12 else:13 #否则通过反射去对象中取值14 column_data = getattr(obj,column)15 16 if type(column_data).__name__ == 'datetime':17 #如果是时间类型,则需要进行格式化显示18 column_data = column_data.strftime('%Y-%m-%d %H:%M:%S')19 row_ele += '%s'%column_data20 return mark_safe(row_ele)
4.动态进行分页参数的切割 render_page_ele
1 @register.simple_tag 2 def render_page_ele(loop_counter,query_sets): 3 #如果当前页数-循环的次数小于1,就展示前面两页和后面两页 4 #例如当前是第五页则展示3,4,5,6,7页 5 if abs(query_sets.number-loop_counter)<=1: 6 ele_class = '' 7 if query_sets.number==loop_counter: 8 ele_class = 'active' 9 ele= '
5.动态加载筛选条件 render_filter_ele
1 @register.simple_tag 2 def render_filter_ele(condition,admin_class,filter_conditions): 3 select_ele = ''22 return mark_safe(select_ele)
当然,上述的代码会导致错误,这是必然发生的,因为我们没有和之后的过滤,排序结合起来,目前只用了分页,所以比较片面,后面还需在功能上进行优化
6.条件过滤
思路:前端传入过滤条件,后端组合成字典,同时过滤掉分页关键字和排序关键字,再将条件封装成字典,按条件查询即可
1 def table_filter(request,admin_class): 2 '''进行条件过滤,并返回过滤后的数据''' 3 filter_condition = {} 4 for k,v in request.GET.items(): 5 #page为分页的字段,o为排序关键字,不是数据库的查询字段,此处要进行过滤 6 if k == 'page' or k == 'o': 7 continue 8 if v: 9 filter_condition[k]=v10 11 return admin_class.model.objects.filter(**filter_condition),filter_condition
7.单条件排序
思路:将前端传入的排序字段,后台拿到排序的关键字进行排序,排序分为正向排序和逆向排序
1 def table_sort(request,objs): 2 #获取前端的分页关键字进行排序 3 orderby_key = request.GET.get('o') 4 if orderby_key: 5 res = objs.order_by(orderby_key) 6 #如果上一次是降序,此时改成升序 7 if orderby_key.startswith('-'): 8 orderby_key = orderby_key.strip('-') 9 else:10 #否则改成降序11 orderby_key = '-%s'%orderby_key12 else:13 res = objs14 return res,orderby_key
8.views修改,分页中集成筛选和排序
1 def display_table_objs(request,app_name,table_name): 2 admin_class = king_admin.enabled_admins[app_name][table_name] 3 #有后端查询出结果集,并对其进行分页操作 4 object_list,filter_conditions = table_filter(request,admin_class) 5 #先过滤,在排序 6 object_list,orderby_key = table_sort(request,object_list) 7 8 paginator = Paginator(object_list, admin_class.list_per_page) 9 page = request.GET.get('page')10 try:11 objects = paginator.page(page)12 except PageNotAnInteger:13 objects = paginator.page(1)14 except EmptyPage:15 objects = paginator.page(paginator.num_pages)16 #传递给前端的参数有model的admin_class,分页的结果集,过滤条件,排序字段,以及上一次的排序字段17 return render(request,'king_admin/table_objs.html',{ 'admin_class':admin_class,18 'query_sets':objects,19 'filter_conditions':filter_conditions,20 'orderby_key':orderby_key,21 'previous_orderby':request.GET.get('o') or ''})
9.tags自定义标签渲染
9.1 筛选条件
1 @register.simple_tag 2 def render_filter_ele(condition,admin_class,filter_conditions): 3 #渲染过滤筛选的条件,返回给前端渲染 4 select_ele = ''23 return mark_safe(select_ele)
9.2 排序关键字
1 @register.simple_tag 2 def build_table_header_column(column,orderby_key,filter_condition): 3 #排序时要携带过滤条件 4 filters = '' 5 for k,v in filter_condition.items(): 6 filters += '&%s=%s'%(k,v) 7 ele = '{column}{sort_icon}' 8 if orderby_key: 9 if orderby_key.startswith('-'):10 sort_icon = ''11 else:12 sort_icon = ''13 14 if orderby_key.strip('-') == column: #排序的就是当前字段15 orderby_key = orderby_key16 17 else:18 orderby_key = column19 sort_icon = ''20 21 else:#没有排序,就默认按照当前列显示22 orderby_key = column23 sort_icon = ''24 return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))
9.3 分页bug修复
1 @register.simple_tag 2 def build_paginations(query_sets,filter_conditions,previous_orderby): 3 '''返回整个的分页元素''' 4 filters = '' 5 for k, v in filter_conditions.items(): 6 filters += '&%s=%s' % (k, v) 7 8 page_btns = '' 9 added_dot_ele = False10 for page_num in query_sets.paginator.page_range:11 #代表最前2页,或最后2页12 if page_num < 3 or page_num > query_sets.paginator.num_pages-2 or \13 abs(query_sets.number - page_num) <= 1:14 ele_class = ''15 if query_sets.number == page_num:16 ele_class = 'active'17 added_dot_ele = False18 page_btns += '
10 前端页面修改
1 {% extends 'king_admin/table_index.html' %} 2 {% load tags %} 3 4 {% block container %} 5660 {% endblock %}79Panel title
81058 5911 { # #}12 2425 { # #}2627 28
4429 {% for column in admin_class.list_display %}30 { # 动态展示表格中的数据,排序关键字,和筛选条件#}31 {% build_table_header_column column orderby_key filter_conditions %}32 {% endfor %}33 34 35 36 { # #}37 {% for obj in query_sets %}3839 {% bulid_table_row obj admin_class %}40 41 {% endfor %}42 43总计:{
{ query_sets.paginator.count }}条45 { # #}46 57
11 排序
后台处理
1 def table_sort(request,objs): 2 #获取前端的分页关键字进行排序 3 orderby_key = request.GET.get('o') 4 if orderby_key: 5 res = objs.order_by(orderby_key) 6 if orderby_key.startswith('-'): 7 orderby_key = orderby_key.strip('-') 8 else: 9 orderby_key = '-%s'%orderby_key10 else:11 res = objs12 return res,orderby_key
tags动态生成标签和触发正序和倒序
1 @register.simple_tag 2 def build_table_header_column(column,orderby_key,filter_condition): 3 filters = '' 4 for k,v in filter_condition.items(): 5 filters += '&%s=%s'%(k,v) 6 #生成每一列表头的超链接,点击触发排序 7 ele = '{column}{sort_icon}' 8 if orderby_key: 9 if orderby_key.startswith('-'):10 sort_icon = ''11 else:12 sort_icon = ''13 14 if orderby_key.strip('-') == column: #排序的就是当前字段15 orderby_key = orderby_key16 17 else:18 orderby_key = column19 sort_icon = ''20 21 else:#没有排序,22 orderby_key = column23 sort_icon = ''24 return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))
12 查找
后台处理
1 def table_search(request,admin_class,object_list):2 search_key = request.GET.get('_q','')3 con = Q()4 con.connector = 'OR'5 for search_field in admin_class.search_fields:6 con.children.append(('%s__contains'%search_field,search_key))7 res = object_list.filter(con)8 return res
原先代码修改
1 def table_filter(request,admin_class): 2 '''进行条件过滤,并返回过滤后的数据''' 3 filter_condition = {} 4 # page为分页的字段,o为排序关键字,_q是搜索关键字,不是数据库的查询字段,此处要进行过滤 5 keywords = ['page','o','_q'] 6 for k,v in request.GET.items(): 7 8 if k in keywords: 9 continue10 if v:11 filter_condition[k]=v12 13 return admin_class.model.objects.filter(**filter_condition),filter_condition
在views中导入utils的查找方法
1 def display_table_objs(request,app_name,table_name): 2 admin_class = king_admin.enabled_admins[app_name][table_name] 3 #有后端查询出结果集,并对其进行分页操作 4 object_list,filter_conditions = table_filter(request,admin_class) 5 #搜索 6 object_list = table_search(request,admin_class,object_list) 7 #先过滤,在排序 8 object_list,orderby_key = table_sort(request,object_list) 9 10 paginator = Paginator(object_list, admin_class.list_per_page)11 page = request.GET.get('page')12 try:13 objects = paginator.page(page)14 except PageNotAnInteger:15 objects = paginator.page(1)16 except EmptyPage:17 objects = paginator.page(paginator.num_pages)18 19 return render(request,'king_admin/table_objs.html',{ 'admin_class':admin_class,20 'query_sets':objects,21 'filter_conditions':filter_conditions,22 'orderby_key':orderby_key,23 'previous_orderby':request.GET.get('o') or '',24 'search_text':request.GET.get('_q') or ''})
前端
123 456 78
13 时间检索
1 @register.simple_tag 2 def render_filter_ele(condition,admin_class,filter_conditions): 3 select_ele = ''42 select_ele=select_ele.format(condition=filter_field_name)43 return mark_safe(select_ele)