1.分页:

分页使用Django内置的分页模块来实现

官方的分页案例

 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render
#后端
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
contacts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
contacts = paginator.page(paginator.num_pages) return render(request, 'list.html', {'contacts': contacts})
#前端
% for contact in contacts %}
{# Each "contact" is a Contact model object. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %}
#分页组件
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">previous</a>
{% endif %} <span class="current">
Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span> {% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">next</a>
{% endif %}
</span>
</div>

在项目中由于分页之前要进行条件筛选和排序,所以分页如下

 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
 def display_table_objs(request,app_name,table_name):
admin_class = king_admin.enabled_admins[app_name][table_name]
#有后端查询出结果集和条件,并对其进行分页操作
object_list,filter_conditions = table_filter(request,admin_class) paginator = Paginator(object_list, admin_class.list_per_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages) return render(request,'king_admin/table_objs.html',{'admin_class':admin_class,
'query_sets':objects,
'filter_conditions':filter_conditions})
 {% block container %}
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
<div class="row">
{# <!--将筛选提交提交到后台进行查询--!>#}
<form method="get">
{% for condition in admin_class.list_filters %}
<div class="col-lg-2">
<span>{{ condition }}</span>
#后台通过条件,数据类,所选条件进行提取结果集
{% render_filter_ele condition admin_class filter_conditions %}
</div>
{% endfor %}
<div class="col-lg-2">
<input type="submit" class="btn btn-info" style="margin-top:20px">
</div>
</form>
</div>
{# <!--动态展示后端的表格--!>#}
<table class="table table-hover">
<thead>
<tr>
{% for column in admin_class.list_display %}
<th>{{ column }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{# <!--动态展示后端的表格中的数据--!>#}
{% for obj in query_sets %}
<tr>
{% bulid_table_row obj admin_class %}
</tr>
{% endfor %}
</tbody>
</table>
{# <!--分页--!>#}
<nav aria-label="...">
<ul class="pagination">
{% if query_sets.has_previous %}
<li><a href="?page={{ query_sets.previous_page_number }}">上一页</a></li>
{% endif %}
{% for loop_counter in query_sets.paginator.page_range %}
{% render_page_ele loop_counter query_sets %}
{% endfor %}
{% if query_sets.has_next %}
<li><a href="?page={{ query_sets.next_page_number }}">下一页</a></li>
{% endif %}
</ul>
</nav>
</div>
</div>
{% endblock %}

自定义标签的tags的方法

1.导入

 from django import template
from django.utils.safestring import mark_safe
register = template.Library()

2.动态加载表格  render_app_name

 @register.simple_tag
def render_app_name(admin_class):
'''渲染动态获取表名'''
return admin_class.model._meta.verbose_name_plural

3.动态展示表格中的数据  build_table_row

 @register.simple_tag
def bulid_table_row(obj,admin_class):
'''生成数据内容的td,填充到table中,展示前端'''
row_ele = ''
for column in admin_class.list_display:
#获取每个字段的类型的对象
field_obj = obj._meta.get_field(column)
#判断是否是choice字段
if field_obj.choices:
#如果是choice字段,则按照choice的值进行展示
column_data = getattr(obj,"get_%s_display"%column)()
else:
#否则通过反射去对象中取值
column_data = getattr(obj,column) if type(column_data).__name__ == 'datetime':
#如果是时间类型,则需要进行格式化显示
column_data = column_data.strftime('%Y-%m-%d %H:%M:%S')
row_ele += '<td>%s</td>'%column_data
return mark_safe(row_ele)

4.动态进行分页参数的切割 render_page_ele

 @register.simple_tag
def render_page_ele(loop_counter,query_sets):
#如果当前页数-循环的次数小于1,就展示前面两页和后面两页
#例如当前是第五页则展示3,4,5,6,7页
if abs(query_sets.number-loop_counter)<=1:
ele_class = ''
if query_sets.number==loop_counter:
ele_class = 'active'
ele= '<li class="%s"><a href="?page=%s">%s</a></li>'%(ele_class,loop_counter,loop_counter)
return mark_safe(ele)
return ''

5.动态加载筛选条件 render_filter_ele

 @register.simple_tag
def render_filter_ele(condition,admin_class,filter_conditions):
select_ele = '<select class="form-control" name="%s"><option value="">----</option>'%condition
field_obj = admin_class.model._meta.get_field(condition)
selected = ''
if field_obj.choices: #choice字段的值的获取
for choice_item in field_obj.choices:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
selected = ''
if type(field_obj).__name__=='ForeignKey':
#外键字段的获取
for choice_item in field_obj.get_choices()[1:]:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
selected = ''
select_ele+='</select>'
return mark_safe(select_ele)

当然,上述的代码会导致错误,这是必然发生的,因为我们没有和之后的过滤,排序结合起来,目前只用了分页,所以比较片面,后面还需在功能上进行优化

6.条件过滤

思路:前端传入过滤条件,后端组合成字典,同时过滤掉分页关键字和排序关键字,再将条件封装成字典,按条件查询即可

 def table_filter(request,admin_class):
'''进行条件过滤,并返回过滤后的数据'''
filter_condition = {}
for k,v in request.GET.items():
#page为分页的字段,o为排序关键字,不是数据库的查询字段,此处要进行过滤
if k == 'page' or k == 'o':
continue
if v:
filter_condition[k]=v return admin_class.model.objects.filter(**filter_condition),filter_condition

7.单条件排序

思路:将前端传入的排序字段,后台拿到排序的关键字进行排序,排序分为正向排序和逆向排序

 def table_sort(request,objs):
#获取前端的分页关键字进行排序
orderby_key = request.GET.get('o')
if orderby_key:
res = objs.order_by(orderby_key)
#如果上一次是降序,此时改成升序
if orderby_key.startswith('-'):
orderby_key = orderby_key.strip('-')
else:
#否则改成降序
orderby_key = '-%s'%orderby_key
else:
res = objs
return res,orderby_key

8.views修改,分页中集成筛选和排序

 def display_table_objs(request,app_name,table_name):
admin_class = king_admin.enabled_admins[app_name][table_name]
#有后端查询出结果集,并对其进行分页操作
object_list,filter_conditions = table_filter(request,admin_class)
#先过滤,在排序
object_list,orderby_key = table_sort(request,object_list) paginator = Paginator(object_list, admin_class.list_per_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages)
#传递给前端的参数有model的admin_class,分页的结果集,过滤条件,排序字段,以及上一次的排序字段
return render(request,'king_admin/table_objs.html',{'admin_class':admin_class,
'query_sets':objects,
'filter_conditions':filter_conditions,
'orderby_key':orderby_key,
'previous_orderby':request.GET.get('o') or ''})

9.tags自定义标签渲染

9.1 筛选条件

 @register.simple_tag
def render_filter_ele(condition,admin_class,filter_conditions):
#渲染过滤筛选的条件,返回给前端渲染
select_ele = '<select class="form-control" name="%s"><option value="">----</option>'%condition
field_obj = admin_class.model._meta.get_field(condition)
selected = ''
if field_obj.choices: #choice字段的值的获取
for choice_item in field_obj.choices:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
selected = ''
if type(field_obj).__name__=='ForeignKey':
#外键字段的获取
for choice_item in field_obj.get_choices()[1:]:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
selected = ''
select_ele+='</select>'
return mark_safe(select_ele)

9.2 排序关键字

 @register.simple_tag
def build_table_header_column(column,orderby_key,filter_condition):
#排序时要携带过滤条件
filters = ''
for k,v in filter_condition.items():
filters += '&%s=%s'%(k,v)
ele = '<th><a href="?{filters}&o={orderby_key}">{column}</a>{sort_icon}</th>'
if orderby_key:
if orderby_key.startswith('-'):
sort_icon = '<span class="glyphicon glyphicon-chevron-up"></span>'
else:
sort_icon = '<span class="glyphicon glyphicon-chevron-down"></span>' if orderby_key.strip('-') == column: #排序的就是当前字段
orderby_key = orderby_key else:
orderby_key = column
sort_icon = '' else:#没有排序,就默认按照当前列显示
orderby_key = column
sort_icon = ''
return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))

9.3 分页bug修复

 @register.simple_tag
def build_paginations(query_sets,filter_conditions,previous_orderby):
'''返回整个的分页元素'''
filters = ''
for k, v in filter_conditions.items():
filters += '&%s=%s' % (k, v) page_btns = ''
added_dot_ele = False
for page_num in query_sets.paginator.page_range:
#代表最前2页,或最后2页
if page_num < 3 or page_num > query_sets.paginator.num_pages-2 or \
abs(query_sets.number - page_num) <= 1:
ele_class = ''
if query_sets.number == page_num:
ele_class = 'active'
added_dot_ele = False
page_btns += '<li class="%s"><a href="?page=%s%s&o=%s">%s</a></li>' % (ele_class, page_num, filters,previous_orderby, page_num)
else:
if not added_dot_ele:#现在还没有加...
page_btns += '<li><a>...</a></li>'
added_dot_ele = True return mark_safe(page_btns)

10 前端页面修改

 {% extends 'king_admin/table_index.html' %}
{% load tags %} {% block container %}
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
<div class="row">
{# <!--将筛选提交提交到后台进行查询--!>#}
<form method="get">
{% for condition in admin_class.list_filters %}
<div class="col-lg-2">
<span>{{ condition }}</span>
{# 后台通过条件,数据类,所选条件进行提取结果集#}
{% render_filter_ele condition admin_class filter_conditions %}
</div>
{% endfor %}
<div class="col-lg-2">
<input type="submit" class="btn btn-info" style="margin-top:20px">
</div>
</form>
</div>
{# <!--动态展示后端的表格--!>#}
<table class="table table-hover">
<thead>
<tr>
{% for column in admin_class.list_display %}
{# 动态展示表格中的数据,排序关键字,和筛选条件#}
{% build_table_header_column column orderby_key filter_conditions %}
{% endfor %}
</tr>
</thead>
<tbody>
{# <!--动态展示后端的表格中的数据--!>#}
{% for obj in query_sets %}
<tr>
{% bulid_table_row obj admin_class %}
</tr>
{% endfor %}
</tbody>
</table>
<p>总计:{{ query_sets.paginator.count }}条</p>
{# <!--分页--!>#}
<nav aria-label="...">
<ul class="pagination">
{% if query_sets.has_previous %}
<li><a href="?page={{ query_sets.previous_page_number }}">上一页</a></li>
{% endif %}
{% build_paginations query_sets filter_conditions previous_orderby %}
{% if query_sets.has_next %}
<li><a href="?page={{ query_sets.next_page_number }}">下一页</a></li>
{% endif %}
</ul>
</nav>
</div> </div>
{% endblock %}

11 排序

后台处理

 def table_sort(request,objs):
#获取前端的分页关键字进行排序
orderby_key = request.GET.get('o')
if orderby_key:
res = objs.order_by(orderby_key)
if orderby_key.startswith('-'):
orderby_key = orderby_key.strip('-')
else:
orderby_key = '-%s'%orderby_key
else:
res = objs
return res,orderby_key

tags动态生成标签和触发正序和倒序

 @register.simple_tag
def build_table_header_column(column,orderby_key,filter_condition):
filters = ''
for k,v in filter_condition.items():
filters += '&%s=%s'%(k,v)
#生成每一列表头的超链接,点击触发排序
ele = '<th><a href="?{filters}&o={orderby_key}">{column}</a>{sort_icon}</th>'
if orderby_key:
if orderby_key.startswith('-'):
sort_icon = '<span class="glyphicon glyphicon-chevron-up"></span>'
else:
sort_icon = '<span class="glyphicon glyphicon-chevron-down"></span>' if orderby_key.strip('-') == column: #排序的就是当前字段
orderby_key = orderby_key else:
orderby_key = column
sort_icon = '' else:#没有排序,
orderby_key = column
sort_icon = ''
return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))

12 查找

后台处理

 def table_search(request,admin_class,object_list):
search_key = request.GET.get('_q','')
con = Q()
con.connector = 'OR'
for search_field in admin_class.search_fields:
con.children.append(('%s__contains'%search_field,search_key))
res = object_list.filter(con)
return res

原先代码修改

 def table_filter(request,admin_class):
'''进行条件过滤,并返回过滤后的数据'''
filter_condition = {}
# page为分页的字段,o为排序关键字,_q是搜索关键字,不是数据库的查询字段,此处要进行过滤
keywords = ['page','o','_q']
for k,v in request.GET.items(): if k in keywords:
continue
if v:
filter_condition[k]=v return admin_class.model.objects.filter(**filter_condition),filter_condition

在views中导入utils的查找方法

 def display_table_objs(request,app_name,table_name):
admin_class = king_admin.enabled_admins[app_name][table_name]
#有后端查询出结果集,并对其进行分页操作
object_list,filter_conditions = table_filter(request,admin_class)
#搜索
object_list = table_search(request,admin_class,object_list)
#先过滤,在排序
object_list,orderby_key = table_sort(request,object_list) paginator = Paginator(object_list, admin_class.list_per_page)
page = request.GET.get('page')
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages) return render(request,'king_admin/table_objs.html',{'admin_class':admin_class,
'query_sets':objects,
'filter_conditions':filter_conditions,
'orderby_key':orderby_key,
'previous_orderby':request.GET.get('o') or '',
'search_text':request.GET.get('_q') or ''})

前端

 <div class="row">
<div class="col-lg-2">
<input type="search" name="_q" style="margin-left:15px" class="form-control" value="{{ search_text }}">
</div>
<div class="col-lg-2">
<button type="submit" class="btn btn-info">搜索</button>
</div>
</div>

13 时间检索

 @register.simple_tag
def render_filter_ele(condition,admin_class,filter_conditions):
select_ele = '<select class="form-control" name="{condition}"><option value="">----</option>'
field_obj = admin_class.model._meta.get_field(condition)
selected = ''
if field_obj.choices: #choice字段的值的获取
for choice_item in field_obj.choices:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
selected = ''
if type(field_obj).__name__=='ForeignKey':
#外键字段的获取
for choice_item in field_obj.get_choices()[1:]:
if filter_conditions.get(condition) == str(choice_item[0]):
selected = 'selected'
select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
selected = ''
if type(field_obj).__name__ in ['DateTimeField','DateField']:
#日期字段获取,通过计算当前时间-天数来实现日期过滤
date_els = []
today_ele = datetime.now().date()
date_els.append(['今天',today_ele])
date_els.append(['昨天',today_ele - timedelta(days=1)])
date_els.append(['近7天', today_ele - timedelta(days=7)])
date_els.append(['本月', today_ele.replace(day=1)])
date_els.append(['近30天', today_ele - timedelta(days=30)])
date_els.append(['近90天', today_ele - timedelta(days=90)])
date_els.append(['近180天', today_ele - timedelta(days=180)])
date_els.append(['本年', today_ele.replace(month=1,day=1)])
date_els.append(['近一年', today_ele - timedelta(days=365)])
selected = ''
for date in date_els:
select_ele += '<option value="%s" %s>%s</option>'%(date[1],selected,date[0])
filter_field_name = '%s__gte'%condition
else:
filter_field_name = condition select_ele+='</select>'
select_ele=select_ele.format(condition=filter_field_name)
return mark_safe(select_ele)

Python CRM项目三的更多相关文章

  1. Python CRM项目二

    一.准备工作 如果没有配置基本的项目,请参考 http://www.cnblogs.com/luhuajun/p/7771196.html 当我们配置完成后首先准备我们的app 创建2个app分别对应 ...

  2. Python CRM项目八

    自定义用户认证 目的:实现Django自定义的认证系统,在生产环境都是根据此代码进行定制的 步骤: 1.在settings文件中配置要使用的类 #命名规则 app名称.类名 AUTH_USER_MOD ...

  3. Python CRM项目一

    开发环境: 语言Python3.X以上 MTV WEB框架 Django 前端框架 jQuery+bootstrap 数据库 MySQL 运行环境 安装Python3.x 安装Django 除IE8以 ...

  4. Python CRM项目七

    仿照Django Admin实现对readonly的字段进行设置 功能点: 1.页面不可进行更改 2.如果改变html代码中的值,则需要进行后端的数据库数据校验 3.可以对某些字段进行自定制校验规则 ...

  5. python实践项目三:将列表添加到字典

    1.创建一个字典,其中键是字符串,描述一个物品,值是一个整型值,说明有多少该物品.例如,字典值{'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, ...

  6. Python CRM项目六

    自定义Django Admin的action 在Django Admin中,可以通过action来自定义一些操作,其中默认的action的功能是选中多条数据来进行删除操作 我们在king_admin中 ...

  7. Python CRM项目四

    实现Django Admin的多对多的复选框效果 效果:左边显示的是未选中的字段,右边显示的是已选中的字段,两边点击的标签可以互相更换 首先在king_admin.py中增加filter_horizo ...

  8. crm 系统项目(三) 自动分页

    crm 系统项目(三) 自动分页 需求: 1. 做一个自动分页, 每15条数据1页 2. 让当前页数在中间显示 3. 上一页, 下一页 注意情况: 1.总页数 小于 规定显示的页数 2. 左右两边极值 ...

  9. CRM项目总结

                CRM项目总结      一:开发背景 在公司日益扩大的过程中,不可避免的会伴随着更多问题出现. 对外 : 如何更好的管理客户与公司的关系?如何更及时的了解客户日益发展的需求变 ...

随机推荐

  1. DOM拓展

    DOM拓展 1.选择符API 所谓选择符API即是根据css选择符选择与某个模式相匹配的DOM元素,jQuery的核心就是通过css选择符查询DOM文档取得元素的引用,从而抛弃了原有繁琐的getELe ...

  2. 新手必须掌握的Linux命令

    一.命令组成 一个完整的命令通常由  命令名称 [命令参数] [命令对象]  组成. 注意:命令名称.命令参数.命令对象之间用空格键隔开. 二.系统工作命令 查看主机名称 echo $HOSTNAME ...

  3. Uva 11729 Commando War (简单贪心)

    Uva 11729  Commando War (简单贪心) There is a war and it doesn't look very promising for your country. N ...

  4. C. The Smallest String Concatenation

    C. The Smallest String Concatenation time limit per test 3 seconds memory limit per test 256 megabyt ...

  5. Linux中安装opencv-3.3.1

    在ubuntu16.04中安装opencv3.3.1的过程中踩了许多坑.一开始直接安装还挺顺利但运行程序时总是提示libgtk2.0-dev和pkg-config没有安装,在安装这两个包的过程中也不顺 ...

  6. C语言mktime()

    最近在调试stm32L151单片机,因为业务需要将从RTC获取的时间转换成时间戳.转换的时候发现获取的时间一直不对.一直被两个问题困扰. 1.从RTC获取出来的月份为什么比实际月份小1? 2.转换得来 ...

  7. Thinkphp 3.2中文章详情页的上一篇 下一篇文章功能

      额 简单2句话解释下 获取上一篇文章的原理,其实就是以当前文章的id为起点进行进行查询,例如id=5的文章 select * from article where (article_id<5 ...

  8. sql子查询

    一.子查询入门: 1.单值子查询: 单值子查询的唯一限制:子查询的返回值必须只有一行记录,而且只能有一列(又被称为标量子查询). 可以使用在select语句的列表.表达式中,以及where语句中等. ...

  9. java实现最小生成树的prim算法和kruskal算法

    在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...

  10. [one day one question] Vue数组变更不能触发刷新

    问题描述:Vue数组变更不能触发刷新,特别是数组的每个元素都是对象的时候,对象中某个属性的值发生变化,根本无法触发Vue的dom刷新,这怎么破? 解决方案:this.$set(array, index ...