1. 程式人生 > >Python CRM項目三

Python CRM項目三

格式化 nbsp 模塊 tar margin 提交 icon btn src

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 }}<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

在項目中由於分頁之前要進行條件篩選和排序,所以分頁如下

技術分享
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.導入

技術分享
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 += <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_ele

技術分享
 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

Python CRM項目三