項目一:CRM(客戶關系管理系統)--2


1. 構造Home首頁

CRM系統是一個相對較復雜的軟件,其中重構admin是最為繁瑣的過程,這個解決掉之后其他的就會很輕松!路漫漫其修遠兮,重寫admin也是一個漫長的過程。

接下來是重寫admin的過程:

1.1. 創建應用

將新的admin作為一個應用,便於擴展和移植。根目錄下,創建應用,並命名為:king_admin(根據自己的喜好)

 

1 ppdeMacBook-Pro:ProjectCRM pp$ pwd
2 /Users/pp/Documents/workplace/pycharm/51cto/ProjectCRM
3 ppdeMacBook-Pro:ProjectCRM pp$ python3.6 manage.py startapp king_admin

 

1.2. 原生admin首頁分析

Django自帶的后台中,首頁顯示的是項目名稱和數據庫表中的字段名稱,並顯示添加和修改功能。(其中,數據庫中綁定了url的映射關系,添加對應的映射名稱即可)

這里不顯示,原生后台的UsersGroups內容,將在后面的權限管理中獨立出來!

1.3. 構造應用路由

1 from django.conf.urls import url
2 from king_admin import views
3 urlpatterns = [
4     url(r'^$', views.index, name='table_index'), #name是對應數據庫中的映射關系
5 ]

 

1.4. 構建前端模板

1.4.1. 創建靜態文件目錄

使用Bootsrap框架,項目中創建statics目錄並在settings.py中添加對應路徑:

1 STATIC_URL = '/static/'
2 #添加以下內容
3 STATICFILES_DIRS = (
4     os.path.join(BASE_DIR, 'statics'),
5 )

1.4.2. 構造底層基礎母板

templates目錄下添加base.html作為所有可繼承模板的母板,主要是用來引入樣式CSSJS

 1 <!DOCTYPE html>
 2 <html lang="en">
 3   <head>
 4     <meta charset="utf-8">
 5     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 6     <meta name="viewport" content="width=device-width, initial-scale=1">
 7     <meta name="description" content="">
 8     <meta name="author" content="">
 9     <title>Django Admin</title>
10     <!-- Bootstrap core CSS -->
11     <link href="/static/css/bootstrap.min.css" rel="stylesheet">
12     <!-- Custom styles for this template -->
13     <link href="/static/css/dashboard.css" rel="stylesheet">
14     <!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
15     <!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
16     <script src="/static/js/ie-emulation-modes-warning.js"></script>
17   </head>
18   <body>
19     <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
20       <div class="container-fluid">
21         <div class="navbar-header">
22           <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
23             <span class="sr-only">Toggle navigation</span>
24             <span class="icon-bar"></span>
25             <span class="icon-bar"></span>
26             <span class="icon-bar"></span>
27           </button>
28           <a class="navbar-brand" href='{% url 'crm_index' %}'>PerfectCRM</a>
29         </div>
30         <div id="navbar" class="navbar-collapse collapse">
31           <ul class="nav navbar-nav navbar-right">
32             <li><a href="#">{{ request.user }}</a></li>
33           </ul>
34         </div>
35       </div>
36     </nav>
37       {% block body-content %}{% endblock %}
38   </body>
39  <!-- Bootstrap core JavaScript
40     ================================================== -->
41     <!-- Placed at the end of the document so the pages load faster -->
42     <script src="/static/js/jquery.min.js"></script>
43     <script src="/static/js/bootstrap.min.js"></script>
44     <script src="/static/js/docs.min.js"></script>
45     <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
46     <script src="/static/js/ie10-viewport-bug-workaround.js"></script>
47 </html>

1.4.3. 創建項目所需主頁

為了更好的擴展和區分,在templates目錄下單獨建立對應項目的存儲模板文件的目錄king_admin,然后創建table_index.html文件。

table_index.html文件內容如下:

 1 {% extends 'base.html' %}   #繼承母板
 2 {% block body-content %} #繼承塊內容
 3     <div class="container " style="margin: 50px;width: auto">
 4     {% block container %} #為后面繼承的塊
 5         <div class="row">
 6             <div class="panel panel-info">
 7               <div class="panel-heading">
 8                 <h3 class="panel-title">King_Admin</h3>
 9               </div>
10               <div class="panel-body">
11                      <table class="table table-hover">
12                         <thead>
13                             <tr>
14                                 <th></th>
15                             </tr>
16                         </thead>
17                         <tbody>
18                                 <tr>
19                                     <td>顯示字段</td>
20                                     <td>添加</td>
21                                     <td>修改</td>
22                                 </tr>
23                         </tbody>
24                      </table>
25               </div>
26             </div>
27         </div>
28     {% endblock %}
29     </div>
30 {% endblock %}

 

1.5. 編寫視圖函數

1 from django.shortcuts import render
2 def index(request):
3     return render(request, 'king_admin/table_index.html')

訪問結果,如下圖:

按鈕修飾自己按照bootstrap耍吧

2. 構造admin注冊功能

前面我們先簡單的編寫了能夠訪問的首頁,但是需要顯示數據庫的字段名稱和項目名稱,必須要有向admin注冊的功能。

除此以外,需要有一個全局變量:

# 構建字典數據結構,存儲的數據類型是:
# {'CRM': {'customerinfo': <class 'kingadmin.kingadmin.CustomerInfoAdmin'>}}
# {'app名稱': {'數據表名' : 界面需要顯示的數據表管理類}

這個全局變量可以傳遞給前端進行前端展示。

其中,構建這個字典所需要的app名稱、數據表名稱需要使用:

app名稱:model_class._meta.app_label

數據表名:model_class._meta.model_name

 1 ppdeMacBook-Pro:ProjectCRM pp$ python3.6 manage.py shell
 2 Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04) 
 3 Type 'copyright', 'credits' or 'license' for more information
 4 IPython 6.1.0 -- An enhanced Interactive Python. Type '?' for help.
 5 
 6 In [1]: from CRM.models import CustomerInfo
 7 
 8 In [2]: CustomerInfo._meta.app_label
 9 Out[2]: 'CRM'
10 
11 In [3]: CustomerInfo._meta.model_name
12 Out[3]: 'customerinfo'

因此,這個注冊函數不僅需要能將兩個類(數據表類,管理類)做一個關聯(能通過管理類訪問數據表類),而且需要將app名稱、數據表名稱、管理類三個對應關系保存起來。

2.1. 原生admin注冊功能分析

在開始,我們訪問原生的admin時,我們需要先注冊數據庫的表名及類的名稱和自定義的類名稱。這流程看起來簡單,后台實現起來其實也是很簡單的!

2.1.1. 仿寫注冊功能

king_admin應用下面添加king_admin.py文件,並編寫以下內容:

 1 #創建基類
 2 class BaseAdmin(object):
 3     list_display = []
 4     list_filter = []
 5     list_per_page = 2
 6 #數據結構容器
 7 enabled_admins = {}
 8 """
 9 {項目名: {表名1: 自定義類1,
10          表名2: 自定義類2,
11         },
12 }
13 """
14 #構造數據結構--->通過models類和自定義類注冊獲取
15 def register(model_class, admin_class=None):
16     if model_class._meta.app_label not in enabled_admins:
17         #添加項目名稱
18         enabled_admins.update({model_class._meta.app_label: {}})
19     #添加自定義類屬性為models類
20     admin_class.model = model_class
21     #通過表名獲取到自定義類
22     enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class

2.2. 進行注冊

 1 from CRM import models
 2 #創建基類
 3 class BaseAdmin(object):
 4     list_display = []
 5     list_filter = []
 6     list_per_page = 2
 7 #數據結構容器
 8 enabled_admins = {}
 9 """
10 {項目名: {表名1: 自定義類1,
11          表名2: 自定義類2,
12         },
13 }
14 """
15 #構造數據結構--->通過models類和自定義類注冊獲取
16 def register(model_class, admin_class=None):
17     if model_class._meta.app_label not in enabled_admins:
18         #添加項目名稱
19         enabled_admins.update({model_class._meta.app_label: {}})
20     #添加自定義類屬性為models類
21     admin_class.model = model_class
22     #通過表名獲取到自定義類
23     enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class
24 #自定義類,顯示特定字段
25 class CustomerAdmin(BaseAdmin):
26     list_display = ['qq','name','source','consultant','consult_course','date','status']
27     list_filters = ['source','consultant','consult_course','status']
28     #model = models.Customer
29 class CustomerFollowUpAdmin(BaseAdmin):
30     list_display = ('customer','consultant','date')
31 #進行注冊,構造數據結構
32 register(models.Customer, CustomerAdmin)
33 register(models.CustomerFollowUp, CustomerFollowUpAdmin)

上面這樣寫在同一個文件中,是不是很別扭,為什么不將注冊功能和注冊行為分開呢??

其實,注冊行為和功能的分開是很有必要的,方便功能的擴展和避免與行為的混淆,更利於架構的優化!

解決如下:

待解決。。。

3. 添加項目名稱和字段

添加的內容,我們需要使用到Djangoshell進行測試查詢我們需要的方法、屬性。

終端中,進入到shell

3.1. 查詢項目名稱

1 >>>python  manage.py  shell
2 Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32
3 Type "help", "copyright", "credits" or "license" for more information.
4 (InteractiveConsole)
5 >>>

king_admin.py中自定義的enable_admins中遍歷即可。


3.2. 查詢字段名稱

查詢字段名稱,最先想到的是當我們操作數據庫時,models中的最接近字段名稱應該是類的名稱也就是表名。因此,先查詢表名下的屬性和方法:

 1 >>> from  CRM  import  models
 2 >>> a = models.Customer
 3 >>> >>> dir(a)
 4 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__modul
 5 e__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', '__subclasshook__', '__weakref__', '_constructor_arg
 6 s', '_db', '_get_queryset_methods', '_hints', '_insert', '_originating_model', '_queryset_class', '_set_creation_counter', '_update', 'aggregate', 'all', 'annotate', 'auto_created
 7 ', 'bulk_create', 'check', 'complex_filter', 'contribute_to_class', 'count', 'create', 'creation_counter', 'dates', 'datetimes', 'db', 'db_manager', 'deconstruct', 'defer', 'disti
 8 nct', 'earliest', 'exclude', 'exists', 'extra', 'filter', 'first', 'from_queryset', 'get', 'get_or_create', 'get_queryset', 'in_bulk', 'iterator', 'last', 'latest', 'model', 'name
 9 ', 'none', 'only', 'order_by', 'prefetch_related', 'raw', 'reverse', 'select_for_update', 'select_related', 'update', 'update_or_create', 'use_in_migrations', 'using', 'values', '
10 values_list']

在上面會看到很多方法和屬性,其中一個很是關鍵:_meta,是對數據表類的操作。繼續:

 1 >>> a._meta
 2 <Options for Customer>
 3 >>> dir(a._meta)
 4 ['FORWARD_PROPERTIES', 'REVERSE_PROPERTIES', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash_
 5 _', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__we
 6 akref__', '_expire_cache', '_forward_fields_map', '_get_fields', '_get_fields_cache', '_ordering_clash', '_populate_directed_relation_graph', '_prepare', '_relation_tree', 'abstra
 7 ct', 'add_field', 'add_manager', 'app_config', 'app_label', 'apps', 'auto_created', 'auto_field', 'base_manager', 'base_manager_name', 'can_migrate', 'concrete_fields', 'concrete_
 8 model', 'contribute_to_class', 'db_table', 'db_tablespace', 'default_apps', 'default_manager', 'default_manager_name', 'default_permissions', 'default_related_name', 'fields', 'fi
 9 elds_map', 'get_ancestor_link', 'get_base_chain', 'get_field', 'get_fields', 'get_latest_by', 'get_parent_list', 'has_auto_field', 'index_together', 'installed', 'label', 'label_l
10 ower', 'local_concrete_fields', 'local_fields', 'local_managers', 'local_many_to_many', 'managed', 'manager_inheritance_from_future', 'managers', 'managers_map', 'many_to_many', '
11 model', 'model_name', 'object_name', 'order_with_respect_to', 'ordering', 'original_attrs', 'parents', 'permissions', 'pk', 'private_fields', 'proxy', 'proxy_for_model', 'related_
12 fkey_lookups', 'related_objects', 'required_db_features', 'required_db_vendor', 'select_on_save', 'setup_pk', 'setup_proxy', 'swappable', 'swapped', 'unique_together', 'verbose_na
13 me', 'verbose_name_plural', 'verbose_name_raw', 'virtual_fields']

很顯然,上面有我們所需要的:

1 >>> a._meta.verbose_name
2 '客戶表'

3.3. 模板中添加名稱

既然,我們所要的數據都找到了來源,剩下的就是在模板中添加進行渲染了。

table_index.html中,添加內容如下(自行對比前面):

 1 {% extends 'base.html' %}
 2 {% load tags %}  #引入自定標簽
 3 {% block body-content %}
 4     <div class="container " style="margin: 50px;width: auto">
 5     {% block container %}
 6         <div class="row">
 7             <div class="panel panel-info">
 8               <div class="panel-heading">
 9                 <h3 class="panel-title">King_Admin</h3>
10               </div>
11               <div class="panel-body">
12                   {{ table_list }}
13                   {% for app_name, table_names in table_list.items %}
14                      <table class="table table-hover">
15                         <thead>
16                             <tr>
17                                 <th>{{ app_name }}</th>
18                             </tr>
19                         </thead>
20                         <tbody>
21                             {% for table_name, admin in table_names.items %}
22                                 <tr>
23                                     {#1.鏈接:url/應用名/表名,2. 顯示中文表名--使用自定義標簽進行處理#}
24                                     <td>{% render_verbose_name admin %}</td>
25                                     <td>添加</td>
26                                     <td>修改</td>
27                                 </tr>
28                             {% endfor %}
29                         </tbody>
30                      </table>
31                   {% endfor %}
32               </div>
33             </div>
34         </div>
35     {% endblock %}
36     </div>
37 {% endblock %}

文件中,需要使用到自定義標簽的功能,具體的使用請看官網或后邊會有自定義標簽!

 模板標簽文件的內容如下:

1 from  django  import template
2 register = template.Library()
3 #------------------------顯示表名稱-->中文---------------------------
4 @register.simple_tag
5 def render_verbose_name(admin_class):
6     return admin_class.model._meta.verbose_name

現實如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM