Python CRM项目三
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项目三的更多相关文章
- Python CRM项目二
一.准备工作 如果没有配置基本的项目,请参考 http://www.cnblogs.com/luhuajun/p/7771196.html 当我们配置完成后首先准备我们的app 创建2个app分别对应 ...
- Python CRM项目八
自定义用户认证 目的:实现Django自定义的认证系统,在生产环境都是根据此代码进行定制的 步骤: 1.在settings文件中配置要使用的类 #命名规则 app名称.类名 AUTH_USER_MOD ...
- Python CRM项目一
开发环境: 语言Python3.X以上 MTV WEB框架 Django 前端框架 jQuery+bootstrap 数据库 MySQL 运行环境 安装Python3.x 安装Django 除IE8以 ...
- Python CRM项目七
仿照Django Admin实现对readonly的字段进行设置 功能点: 1.页面不可进行更改 2.如果改变html代码中的值,则需要进行后端的数据库数据校验 3.可以对某些字段进行自定制校验规则 ...
- python实践项目三:将列表添加到字典
1.创建一个字典,其中键是字符串,描述一个物品,值是一个整型值,说明有多少该物品.例如,字典值{'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, ...
- Python CRM项目六
自定义Django Admin的action 在Django Admin中,可以通过action来自定义一些操作,其中默认的action的功能是选中多条数据来进行删除操作 我们在king_admin中 ...
- Python CRM项目四
实现Django Admin的多对多的复选框效果 效果:左边显示的是未选中的字段,右边显示的是已选中的字段,两边点击的标签可以互相更换 首先在king_admin.py中增加filter_horizo ...
- crm 系统项目(三) 自动分页
crm 系统项目(三) 自动分页 需求: 1. 做一个自动分页, 每15条数据1页 2. 让当前页数在中间显示 3. 上一页, 下一页 注意情况: 1.总页数 小于 规定显示的页数 2. 左右两边极值 ...
- CRM项目总结
CRM项目总结 一:开发背景 在公司日益扩大的过程中,不可避免的会伴随着更多问题出现. 对外 : 如何更好的管理客户与公司的关系?如何更及时的了解客户日益发展的需求变 ...
随机推荐
- ESLint 使用入门 - 来自推酷
在团队协作中,为避免低级 Bug.产出风格统一的代码,会预先制定编码规范.使用 Lint 工具和代码风格检测工具,则可以辅助编码规范执行,有效控制代码质量. 在以前的项目中,我们选择 JSHint 和 ...
- 2017年第六届数学中国数学建模国际赛(小美赛)C题解题思路
这篇文章主要是介绍下C题的解题思路,首先我们对这道C题进行一个整体的概括,结构如下: C题:经济类 第一问:发现危险人群. 发现:欺诈的方式开始.雇佣或浪漫的承诺. 数据→确定特定的经济萧条地区→确定 ...
- Codeforces Round #404 (Div. 2)(A.水,暴力,B,排序,贪心)
A. Anton and Polyhedrons time limit per test:2 seconds memory limit per test:256 megabytes input:sta ...
- [bzoj1587] [Usaco2009 Mar]Cleaning Up 打扫卫生
首先(看题解)可得...分成的任意一段中的不同颜色个数都<=根号n...不然的话直接分成n段会更优= = 然后就好做多了.. 先预处理出对于每头牛i,和它颜色相同的前一头和后一头牛的位置. 假设 ...
- hdu_1033(我怎么找到的这么水的题,只为保存代码。。。)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> us ...
- jsp的内置对象
JSP内置对象即无需声明就可以直接使用的对象实例,在实际的开发过程中,比较常用的JSP对象有request,response,session,out和application等,笔者在本文章中将简单介绍 ...
- HDU--1164
Eddy's research I Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- android新闻App源码、仿微信源码、地图音乐源码等
Android精选源码 一款实用的休闲类App,新闻视频和技术应有尽有. android实现交互式K线图表源码 android新闻客户端和服务器源码 android MatetialDesign设计 ...
- 独立成分分析(ICA)的模拟实验(R语言)
本笔记是ESL14.7节图14.42的模拟过程.第一部分将以ProDenICA法为例试图介绍ICA的整个计算过程:第二部分将比较ProDenICA.FastICA以及KernelICA这种方法,试图重 ...
- [国嵌攻略][142][LCD驱动程序架构]
LCD裸机驱动回顾 1.LCD初始化 1.1.控制器初始化 1.2.端口初始化 1.3.指明了帧缓冲 2.LCD图形显示 2.1.将图形数据写入帧缓冲 Linux帧缓冲体验 把图片转换成开发板屏对应的 ...