Python CRM项目三

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
class="pagination"> 27 class="step-links"> 28 {% if contacts.has_previous %} 29 "?page={{ contacts.previous_page_number }}">previous 30 {% endif %} 31 32 class="current"> 33 Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}. 34 35 36 {% if contacts.has_next %} 37 "?page={{ contacts.next_page_number }}">next 38 {% endif %} 39 40
View Code

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

1 from django.core.paginator import Paginator,EmptyPage, PageNotAnInteger
View Code
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
View Code
 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})
View Code
 1 {% block container %}
 2     
class="panel panel-info"> 3
class="panel-heading"> 4

class="panel-title">Panel title

5
6
class="panel-body"> 7
class="row"> 8 {# #} 9
"get"> 10 {% for condition in admin_class.list_filters %} 11
class="col-lg-2"> 12 {{ condition }} 13 #后台通过条件,数据类,所选条件进行提取结果集 14 {% render_filter_ele condition admin_class filter_conditions %} 15
16 {% endfor %} 17
class="col-lg-2"> 18 "submit" class="btn btn-info" style="margin-top:20px"> 19
20
21
22 {# #} 23 class="table table-hover"> 242526 {% for column in admin_class.list_display %} 2728 {% endfor %} 29303132 {# #}33 {% for obj in query_sets %} 3435 {% bulid_table_row obj admin_class %} 3637 {% endfor %} 3839
{{ column }}
40 {# #} 41 54
55
56 {% endblock %}
View Code

自定义标签的tags的方法

1.导入

1 from django import template
2 from django.utils.safestring import mark_safe
3 register = template.Library()
View Code

2.动态加载表格  render_app_name

1 @register.simple_tag
2 def render_app_name(admin_class):
3     '''渲染动态获取表名'''
4     return admin_class.model._meta.verbose_name_plural
View Code

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_data
20     return mark_safe(row_ele)
View Code

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= '
  • %s
  • '%(ele_class,loop_counter,loop_counter) 10 return mark_safe(ele) 11 return ''
    View Code

    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)
    View Code

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

    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]=v
    10 
    11     return admin_class.model.objects.filter(**filter_condition),filter_condition
    View Code

    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_key
    12     else:
    13         res = objs
    14     return res,orderby_key
    View Code

    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 ''})
    View Code

    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)
    View Code

    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_key
    16 
    17         else:
    18             orderby_key = column
    19             sort_icon = ''
    20 
    21     else:#没有排序,就默认按照当前列显示
    22         orderby_key = column
    23         sort_icon = ''
    24     return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))
    View Code

    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 = False
    10     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 = False
    18             page_btns += '
  • %s
  • ' % (ele_class, page_num, filters,previous_orderby, page_num) 19 else: 20 if not added_dot_ele:#现在还没有加... 21 page_btns += '
  • ...
  • ' 22 added_dot_ele = True 23 24 return mark_safe(page_btns)
    View Code

    10 前端页面修改

     1 {% extends 'king_admin/table_index.html' %}
     2 {% load tags %}
     3 
     4 {% block container %}
     5     
    class="panel panel-info"> 6
    class="panel-heading"> 7

    class="panel-title">Panel title

    8
    9
    class="panel-body"> 10
    class="row"> 11 {# #} 12
    "get"> 13 {% for condition in admin_class.list_filters %} 14
    class="col-lg-2"> 15 {{ condition }} 16 {# 后台通过条件,数据类,所选条件进行提取结果集#} 17 {% render_filter_ele condition admin_class filter_conditions %} 18
    19 {% endfor %} 20
    class="col-lg-2"> 21 "submit" class="btn btn-info" style="margin-top:20px"> 22
    23
    24
    25 {# #} 26 class="table table-hover"> 272829 {% for column in admin_class.list_display %} 30 {# 动态展示表格中的数据,排序关键字,和筛选条件#}31 {% build_table_header_column column orderby_key filter_conditions %} 32 {% endfor %} 33343536 {# #}37 {% for obj in query_sets %} 3839 {% bulid_table_row obj admin_class %} 4041 {% endfor %} 4243
    44

    总计:{{ query_sets.paginator.count }}条

    45 {# #} 46 57
    58 59
    60 {% endblock %}
    View Code

     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_key
    10     else:
    11         res = objs
    12     return res,orderby_key
    View Code

    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_key
    16 
    17         else:
    18             orderby_key = column
    19             sort_icon = ''
    20 
    21     else:#没有排序,
    22         orderby_key = column
    23         sort_icon = ''
    24     return mark_safe(ele.format(orderby_key=orderby_key,column=column,sort_icon=sort_icon,filters=filters))
    View Code

    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
    View Code

    原先代码修改

     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             continue
    10         if v:
    11             filter_condition[k]=v
    12 
    13     return admin_class.model.objects.filter(**filter_condition),filter_condition
    View Code

    在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 ''})
    View Code

    前端

    1 
    class="row"> 2
    class="col-lg-2"> 3 "search" name="_q" style="margin-left:15px" class="form-control" value="{{ search_text }}"> 4
    5
    class="col-lg-2"> 6 7
    8
    View Code

    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)
    View Code

     

    你可能感兴趣的:(Python CRM项目三)