项目一:CRM(客户关系管理系统)--3
前面我们已经将首页的雏形搞定,关于修饰部分,后面直接套用模板即可!接下来,我们需要做的是添加二级页面,也就是说,点击‘客户表’进入到独立的显示页面可以进行独立的操作。
1. 添加二级页面
1.1. 构造二级页面的路由
1.1.1. 原生admin二级页面路由分析
原生admin
二级页面路由分析
先看图:
从图中,我们可以知道该url
的构成条件:域名/后台名称/应用名称/表名/
1.1.2. 仿造二级页面路由
在独立应用king_admin
中的urls.py
中添加,如下内容:
1 from django.conf.urls import url 2 from king_admin import views 3 urlpatterns = [ 4 url(r'^$', views.index, name='table_index'), 5 url(r'^(\w+)/(\w+)/$', views.display_objects, name='display_objects'), #添加该数据,参数分别表示应用名和表名,name同样表示映射关系的引用 6 ]
1.2. 构造二级页面模板
在king_admin
模板目录下创建table_objs.html
文件,然后只需要继承一级页面即可:
1 {% extends 'king_admin/table_index.html' %} 2 {% block container %} 3 <div class="panel panel-info"> 4 <div class="panel-heading"> 5 <h3 class="panel-title">Panel title</h3> 6 </div> 7 <div class="panel-body"> 8 <div class="row"> 9 </div> 10 {#具体的表格内容展示 #} 11 <table class="table table-hover"> 12 <thead> 13 <tr> 14 <th> title_name </th> 15 </tr> 16 </thead> 17 <tbody> 18 <tr> </tr> 19 </tbody> 20 </table> 21 </div> 22 </div> 23 {% endblock %}
1.3. 编写二级页面视图函数
内容如下:
1 def display_objects(request, app_name, table_name): 2 return render(request, 'king_admin/table_objs.html')
1.4. 在首页中添加链接入口
我们还要在首页文件中添加入口标签<a></a>
,具体内容如下:
table_index.html
文件添加内容如下:
1 ... 2 <tbody> 3 {% for table_name, admin in table_names.items %} 4 <tr> 5 {#1.链接:url/应用名/表名,2. 显示中文表名--使用自定义标签进行处理#} 6 <td><a href="{% url 'display_objects' app_name table_name %}">{% render_verbose_name admin %}</a></td> 7 <td>添加</td> 8 <td>修改</td> 9 </tr> 10 {% endfor %} 11 </tbody> 12 13 ...
这样,我们就能够通过首页进入到二级页面了,当然现在的二级页面还什么都没有,如图:
2. 添加二级页面显示内容
二级页面中,我们看到有很多的内容,这里先添加显示表格的相关内容。
1. 需要显示列名,即对应list_display列表中需要列出的列名,但是list_display中显示的列名是数据表的列名,也即是英文的,需要显示为数据表列名的verbose_name:
1 In [177]: query_sets = CustomerInfo.objects.all() 2 3 In [178]: query_set = query_sets[0] 4 5 In [179]: query_set._meta.get_field('qq').verbose_name 6 Out[179]: 'QQ号码'
2. 查询数据表中的所有数据:
1 In [180]: CustomerInfoAdmin.model.objects.all() 2 Out[180]: <QuerySet [<CustomerInfo: 123456789>, <CustomerInfo: 123456678>, <CustomerInfo: 12345678910>, <CustomerInfo: 12345678911>, <CustomerInfo: 12345678912>, <CustomerInfo: 12345678915>]>
3. 获取数据表的列名:
1 In [181]: CustomerInfoAdmin.model._meta.fields 2 Out[181]: 3 (<django.db.models.fields.AutoField: id>, 4 <django.db.models.fields.CharField: name>, 5 <django.db.models.fields.CharField: qq>, 6 <django.db.models.fields.CharField: qq_name>, 7 <django.db.models.fields.CharField: phone>, 8 <django.db.models.fields.IntegerField: refer_path>, 9 <django.db.models.fields.CharField: refer_from>, 10 <django.db.models.fields.related.ForeignKey: consult_course>, 11 <django.db.models.fields.TextField: consult_content>, 12 <django.db.models.fields.related.ForeignKey: consultant>, 13 <django.db.models.fields.DateTimeField: date>, 14 <django.db.models.fields.TextField: remark>, 15 <django.db.models.fields.SmallIntegerField: status>) 16 17 In [182]: CustomerInfoAdmin.model._meta.fields[0].name 18 Out[182]: 'id'
4. 如果是choices字段即:
1 source_choices = ( 2 (0, '转介绍'), 3 (1, 'QQ群'), 4 (2, '官网'), 5 (3, '百度推广'), 6 (4, '51CTO'), 7 (5, '知乎'), 8 (6, '市场部推广'), 9 ) 10 refer_path = models.IntegerField(choices=source_choices, verbose_name='从什么途径了解的课程')
这种字段信息,在数据前端展示的时候该列只会显示数字,为了能显示对应的含义,需要针对每个列名进行判断,如果列.choices不为空,就说明该字段就是这类字段信息:
1 In [185]: CustomerInfoAdmin.model._meta.fields[0].choices 2 Out[185]: [] 3 4 In [186]: CustomerInfoAdmin.model._meta.fields[5].choices 5 Out[186]: 6 ((0, '转介绍'), 7 (1, 'QQ群'), 8 (2, '官网'), 9 (3, '百度推广'), 10 (4, '51CTO'), 11 (5, '知乎'), 12 (6, '市场部推广')) 13 14 In [187]: CustomerInfoAdmin.model._meta.fields[12].choices 15 Out[187]: ((0, '已报名'), (1, '未报名'), (2, '已退学'), (3, '其他')) 16 17 In [188]: CustomerInfoAdmin.model._meta.fields[12].choices[3][1] 18 Out[188]: '其他'
2.1. 原生admin添加显示内容分析
我们之前在原生的admin
中进行注册时,添加了以下内容:
1 #自定义操作 2 class CustomerAdmin(admin.ModelAdmin): 3 #显示字段 4 list_display = ('name', 'id','qq','source','consultant','content','status','date') 5 #过滤 6 list_filter = ('source','consultant','date') 7 #搜索 8 search_fields = ('qq','name') 9 raw_id_fields = ('consult_course',) 10 #水平显示 11 filter_horizontal = ('tags',) 12 #可编辑 13 list_editable = ('status',) 14 class UserProfileAdmin(admin.ModelAdmin): 15 list_display = ('user','name')
2.2. king_admin中添加显示字段
在我们自己编写的admin
中添加:
1 #自定义类,显示特定字段 2 class CustomerAdmin(BaseAdmin): 3 #显示字段 4 list_display = ['qq','name','source','consultant','consult_course','date','status'] 5 #过滤 6 list_filters = ['source','consultant','consult_course','status'] 7 #model = models.Customer<br> 8 class CustomerFollowUpAdmin(BaseAdmin): 9 list_display = ('customer','consultant','date')
过滤是后边的内容,当前可以不加。
2.3. 根据字段提取数据
要显示的字段都有了,接下要根据这些字段到数据库中获取数据,并在模板渲染即可!
编写视图函数即可:
1 def display_objects(request, app_name, table_name): 2 #获取自定义的admin_class 3 admin_class = enabled_admins[app_name][table_name] 4 #数据查询 5 query_set = admin_class.model.objects.all() 6 7 return render(request, 'king_admin/table_objs.html', 8 {'admin_class': admin_class, 9 'query_set': query_set})
2.4. 模板添加数据并渲染
在二级页面的模板中,添加如下内容:
1 {% extends 'king_admin/table_index.html' %} 2 {% load tags %} 3 {% block container %} 4 <div class="panel panel-info"> 5 <div class="panel-heading"> 6 <h3 class="panel-title">Panel title</h3> 7 </div> 8 <div class="panel-body"> 9 <div class="row"> 10 </div> 11 {#具体的表格内容展示 #} 12 <table class="table table-hover"> 13 <thead> 14 <tr> 15 {% for title_name in admin_class.list_display %} 16 <th>{{ title_name }}</th> 17 {% endfor %} 18 </tr> 19 </thead> 20 <tbody> 21 {% for item in query_set %} 22 <tr> 23 {#创建列表行数据#} 24 {% create_row item admin_class %} 25 </tr> 26 {% endfor %} 27 </tbody> 28 </table> 29 </div> 30 </div> 31 {% endblock %}
文件内容分析:
- 自定义标签
使用它原因和首页是一样的,这里不再赘述!
自定义标签文件的内容:
1 from django import template 2 from django.utils.safestring import mark_safe 3 register = template.Library() 4 #------------------------显示表名称-->中文--------------------------- 5 @register.simple_tag 6 def render_verbose_name(admin_class): 7 return admin_class.model._meta.verbose_name 8 #-------------------------创建表格行数据----------------------------- 9 @register.simple_tag 10 def create_row(query_set_obj, admin_class): 11 #创建标签元素--空,None不行 12 element = '' 13 14 #遍历要显示的models字段 15 for row in admin_class.list_display: 16 #获取显示字段对应的字段对象 17 field_obj = admin_class.model._meta.get_field(row) 18 #获取数据 19 #判断choice 20 if field_obj.choices: 21 #通过反射获取对象里面的值,并执行该方法get_字段_display()获取choices里面的数值 22 row_data = getattr(query_set_obj, 'get_{0}_display'.format(row))() 23 else: 24 row_data = getattr(query_set_obj, row) 25 26 #时间格式转换 27 if type(row_data).__name__ == 'datetime': 28 row_data = row_data.strftime('%Y-%m-%d %H-%M-%S') 29 30 #标签元素的拼接 31 element += "<td>{0}</td>".format(row_data) 32 return mark_safe(element)
页面显示效果如下: