Python CRM項目三

1.分頁:html

分頁使用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 }}<br />
23     ...
24 {% endfor %}
25 #分頁組件
26 <div class="pagination">
27     <span class="step-links">
28         {% if contacts.has_previous %}
29             <a href="?page={{ contacts.previous_page_number }}">previous</a>
30         {% endif %}
31 
32         <span class="current">
33             Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
34         </span>
35 
36         {% if contacts.has_next %}
37             <a href="?page={{ contacts.next_page_number }}">next</a>
38         {% endif %}
39     </span>
40 </div>
View Code

在項目中因爲分頁以前要進行條件篩選和排序,因此分頁以下django

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     <div class="panel panel-info">
 3         <div class="panel-heading">
 4             <h3 class="panel-title">Panel title</h3>
 5         </div>
 6         <div class="panel-body">
 7             <div class="row">
 8 {#            <!--將篩選提交提交到後臺進行查詢--!>#}
 9                 <form method="get">
10                     {% for condition in admin_class.list_filters %}
11                         <div class="col-lg-2">
12                             <span>{{  condition }}</span>
13                             #後臺經過條件,數據類,所選條件進行提取結果集
14                             {% render_filter_ele condition admin_class filter_conditions %}
15                         </div>
16                     {% endfor %}
17                     <div class="col-lg-2">
18                         <input type="submit" class="btn btn-info" style="margin-top:20px">
19                     </div>
20                 </form>
21             </div>
22         {#            <!--動態展現後端的表格--!>#}
23             <table class="table table-hover">
24                 <thead>
25                     <tr>
26                         {% for column in admin_class.list_display %}
27                             <th>{{ column }}</th>
28                         {% endfor %}
29                     </tr>
30                 </thead>
31                 <tbody>
32 {#            <!--動態展現後端的表格中的數據--!>#}
33                     {% for obj in query_sets %}
34                         <tr>
35                             {% bulid_table_row obj admin_class %}
36                         </tr>
37                     {% endfor %}
38                 </tbody>
39             </table>
40         {#            <!--分頁--!>#}
41             <nav aria-label="...">
42               <ul class="pagination">
43                   {% if query_sets.has_previous %}
44                      <li><a href="?page={{ query_sets.previous_page_number }}">上一頁</a></li>
45                   {% endif %}
46                   {% for loop_counter in query_sets.paginator.page_range %}
47                     {% render_page_ele loop_counter query_sets %}
48                   {% endfor %}
49                   {% if query_sets.has_next %}
50                      <li><a href="?page={{ query_sets.next_page_number }}">下一頁</a></li>
51                   {% endif %}
52               </ul>
53             </nav>
54         </div>
55     </div>
56 {% endblock %}
View Code

自定義標籤的tags的方法後端

1.導入app

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

2.動態加載表格  render_app_nameide

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_rowoop

 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 += '<td>%s</td>'%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= '<li class="%s"><a href="?page=%s">%s</a></li>'%(ele_class,loop_counter,loop_counter)
10         return mark_safe(ele)
11     return ''
View Code

5.動態加載篩選條件 render_filter_eleui

 1 @register.simple_tag
 2 def render_filter_ele(condition,admin_class,filter_conditions):
 3     select_ele = '<select class="form-control" name="%s"><option value="">----</option>'%condition
 4     field_obj = admin_class.model._meta.get_field(condition)
 5     selected = ''
 6     if field_obj.choices:
 7 
 8         #choice字段的值的獲取
 9         for choice_item in field_obj.choices:
10             if filter_conditions.get(condition) == str(choice_item[0]):
11                 selected = 'selected'
12             select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
13             selected = ''
14     if type(field_obj).__name__=='ForeignKey':
15         #外鍵字段的獲取
16         for choice_item in field_obj.get_choices()[1:]:
17             if filter_conditions.get(condition) == str(choice_item[0]):
18                 selected = 'selected'
19             select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
20             selected = ''
21     select_ele+='</select>'
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 = '<select class="form-control" name="%s"><option value="">----</option>'%condition
 5     field_obj = admin_class.model._meta.get_field(condition)
 6     selected = ''
 7     if field_obj.choices:
 8 
 9         #choice字段的值的獲取
10         for choice_item in field_obj.choices:
11             if filter_conditions.get(condition) == str(choice_item[0]):
12                 selected = 'selected'
13             select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
14             selected = ''
15     if type(field_obj).__name__=='ForeignKey':
16         #外鍵字段的獲取
17         for choice_item in field_obj.get_choices()[1:]:
18             if filter_conditions.get(condition) == str(choice_item[0]):
19                 selected = 'selected'
20             select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
21             selected = ''
22     select_ele+='</select>'
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 = '<th><a href="?{filters}&o={orderby_key}">{column}</a>{sort_icon}</th>'
 8     if orderby_key:
 9         if orderby_key.startswith('-'):
10             sort_icon = '<span class="glyphicon glyphicon-chevron-up"></span>'
11         else:
12             sort_icon = '<span class="glyphicon glyphicon-chevron-down"></span>'
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 += '<li class="%s"><a href="?page=%s%s&o=%s">%s</a></li>' % (ele_class, page_num, filters,previous_orderby, page_num)
19         else:
20             if not added_dot_ele:#如今尚未加...
21                 page_btns += '<li><a>...</a></li>'
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     <div class="panel panel-info">
 6         <div class="panel-heading">
 7             <h3 class="panel-title">Panel title</h3>
 8         </div>
 9         <div class="panel-body">
10             <div class="row">
11 {#            <!--將篩選提交提交到後臺進行查詢--!>#}
12                 <form method="get">
13                     {% for condition in admin_class.list_filters %}
14                         <div class="col-lg-2">
15                             <span>{{  condition }}</span>
16 {#                            後臺經過條件,數據類,所選條件進行提取結果集#}
17                             {% render_filter_ele condition admin_class filter_conditions %}
18                         </div>
19                     {% endfor %}
20                     <div class="col-lg-2">
21                         <input type="submit" class="btn btn-info" style="margin-top:20px">
22                     </div>
23                 </form>
24             </div>
25         {#            <!--動態展現後端的表格--!>#}
26             <table class="table table-hover">
27                 <thead>
28                     <tr>
29                         {% for column in admin_class.list_display %}
30 {#                            動態展現表格中的數據,排序關鍵字,和篩選條件#}
31                             {% build_table_header_column column orderby_key filter_conditions %}
32                         {% endfor %}
33                     </tr>
34                 </thead>
35                 <tbody>
36 {#            <!--動態展現後端的表格中的數據--!>#}
37                     {% for obj in query_sets %}
38                         <tr>
39                             {% bulid_table_row obj admin_class %}
40                         </tr>
41                     {% endfor %}
42                 </tbody>
43             </table>
44             <p>總計:{{ query_sets.paginator.count }}條</p>
45         {#            <!--分頁--!>#}
46             <nav aria-label="...">
47               <ul class="pagination">
48                   {% if query_sets.has_previous %}
49                      <li><a href="?page={{ query_sets.previous_page_number }}">上一頁</a></li>
50                   {% endif %}
51                   {% build_paginations query_sets filter_conditions previous_orderby %}
52                   {% if query_sets.has_next %}
53                      <li><a href="?page={{ query_sets.next_page_number }}">下一頁</a></li>
54                   {% endif %}
55               </ul>
56             </nav>
57         </div>
58 
59     </div>
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 = '<th><a href="?{filters}&o={orderby_key}">{column}</a>{sort_icon}</th>'
 8     if orderby_key:
 9         if orderby_key.startswith('-'):
10             sort_icon = '<span class="glyphicon glyphicon-chevron-up"></span>'
11         else:
12             sort_icon = '<span class="glyphicon glyphicon-chevron-down"></span>'
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 <div class="row">
2                         <div class="col-lg-2">
3                             <input type="search" name="_q" style="margin-left:15px" class="form-control" value="{{ search_text }}">
4                         </div>
5                         <div class="col-lg-2">
6                             <button type="submit" class="btn btn-info">搜索</button>
7                         </div>
8                     </div>
View Code

13 時間檢索

 1 @register.simple_tag
 2 def render_filter_ele(condition,admin_class,filter_conditions):
 3     select_ele = '<select class="form-control" name="{condition}"><option value="">----</option>'
 4     field_obj = admin_class.model._meta.get_field(condition)
 5     selected = ''
 6     if field_obj.choices:
 7 
 8         #choice字段的值的獲取
 9         for choice_item in field_obj.choices:
10             if filter_conditions.get(condition) == str(choice_item[0]):
11                 selected = 'selected'
12             select_ele += '<option value="%s" %s>%s</option>'%(choice_item[0],selected,choice_item[1])
13             selected = ''
14     if type(field_obj).__name__=='ForeignKey':
15         #外鍵字段的獲取
16         for choice_item in field_obj.get_choices()[1:]:
17             if filter_conditions.get(condition) == str(choice_item[0]):
18                 selected = 'selected'
19             select_ele += '<option value="%s" %s>%s</option>' % (choice_item[0], selected,choice_item[1])
20             selected = ''
21     if type(field_obj).__name__ in ['DateTimeField','DateField']:
22         #日期字段獲取,經過計算當前時間-天數來實現日期過濾
23         date_els = []
24         today_ele = datetime.now().date()
25         date_els.append(['今天',today_ele])
26         date_els.append(['昨天',today_ele - timedelta(days=1)])
27         date_els.append(['近7天', today_ele - timedelta(days=7)])
28         date_els.append(['本月', today_ele.replace(day=1)])
29         date_els.append(['近30天', today_ele - timedelta(days=30)])
30         date_els.append(['近90天', today_ele - timedelta(days=90)])
31         date_els.append(['近180天', today_ele - timedelta(days=180)])
32         date_els.append(['本年', today_ele.replace(month=1,day=1)])
33         date_els.append(['近一年', today_ele - timedelta(days=365)])
34         selected = ''
35         for date in date_els:
36             select_ele += '<option value="%s" %s>%s</option>'%(date[1],selected,date[0])
37         filter_field_name = '%s__gte'%condition
38     else:
39         filter_field_name = condition
40 
41     select_ele+='</select>'
42     select_ele=select_ele.format(condition=filter_field_name)
43     return mark_safe(select_ele)
View Code
相關文章
相關標籤/搜索