西游之路——python全栈——CRM项目之Kingadmin开发

一、Kingadmin设计

  1、原因

    由于每个用户都需要增删改查,所有开发一个Kingadmin模块,支持所有用户,只需配置注册即可

  2、创建APP之Kingadmin,并把statics、templates及相关的views跟urls导入致Kingadmin

二、自动发现及注册功能开发

  1、程序启动则自动触发注册

    流程:  程序启动    ==>   解析views视图   ==>   调用app_setup模块下kingadmin_auto_discover函数   ==>   逐一触发其app下的Kingadmin模块   ==>   调用sites模块实例化后创建一个字典(只实例化一次),再执行register函数进行注册动作,并把信息封装到字典

==========================

1 from kingadmin import app_setup
2 app_setup.kingadmin_auto_discover()
解析views视图

==========================

1 from django import conf   # 动态获取settings配置
2 
3 def kingadmin_auto_discover():
4     for app_name in conf.settings.INSTALLED_APPS:
5         try:
6             mod = __import__('%s.kingadmin' % app_name)
7             print(mod.kingadmin)
8         except ModuleNotFoundError:
9             pass
app_setup下kingadmin_auto_discove函数

==========================

 1 from crm import models
 2 from kingadmin.sites import site
 3 from kingadmin.admin_base import BaseKingAdmin
 4 
 5 class CustomAdmin(BaseKingAdmin):
 6     list_display = ['name', 'source', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'date']
 7     list_filter = ['source', 'consultant', 'status', 'date']
 8 
 9 site.register(models.CustomerInfo,CustomAdmin)
10 site.register(models.Menus)
11 site.register(models.UserProFile)
12 site.register(models.StudyRecord)
13 site.register(models.CustomerFollowUp)
逐一触发其app下的Kingadmin模块(其中一个)

=========================

 1 from kingadmin.admin_base import BaseKingAdmin
 2 
 3 class AdminSite(object):
 4     def __init__(self):
 5         self.enabled_admins = {}
 6 
 7     def register(self,model_class,admin_class=None):
 8         """注册admin表"""
 9         # 根据model中类名获取APP名
10         app_name = model_class._meta.app_label
11         # 根据model中类名获取表名,类名的小写
12         model_name = model_class._meta.model_name
13 
14         # 不传值时默认BaseKingAdmin,并实例化
15         if not admin_class:
16             admin_class = BaseKingAdmin()
17         else:
18             # 每次实例化,防止使用同一内存地址
19             admin_class = admin_class()
20         # ??????? admin_class为对象才能 .model添加存入对象
21         admin_class.model = model_class  # 把model_class赋值给admin_class为了能关联起来
22         if app_name not in self.enabled_admins:
23             self.enabled_admins[app_name] = {}
24         self.enabled_admins[app_name][model_name] = admin_class
25 
26         print(model_class,admin_class)
27 
28 site = AdminSite()   # 只实例化一次,后面的导入为调用对象
行register函数进行注册动作,并封装

========================

1 dict = {
2     'app1':{'表名1':'自定义类名1','表名2':'自定义类名2'},
3     'app2':{'表名1':'自定义类名1','表名2':'自定义类名2'},
4 }
字典结构

三、APP首页开发

  1、URL

re_path('^kingadmin/', include('kingadmin.urls')),


urlpatterns = [
    re_path('^$', views.app_index,name='app_index'),
    re_path('^/(\w+)/(\w+)/$', views.table_obj_list,name='table_obj_list'),
    re_path('^login/', views.acc_login),
    re_path('^logout/', views.acc_logout,name='logout'),
]

  2、视图函数

1 def app_index(request):
2     return render(request, 'kingadmin/app_index.html',{'site':site})
Kingadmin/views.py

  3、setting配置与templates模块

注意:从上往下找

  

  4、templates模块

 1 {% extends 'kingadmin/index.html' %}
 2 
 3 {% block right-content-container %}
 4     <h1 class="page-header">app</h1>
 5 
 6     <div>
 7         {% for app_name,app_tables in site.enabled_admins.items %}
 8         <table class="table table-striped">
 9             <thead>
10                 <tr>
11                     <th>{{app_name}}</th>
12                 </tr>
13             </thead>
14             <tbody>
15                 {% for model_name in app_tables %}
16                 <tr>
17                     <td><a href="{% url 'table_obj_list' app_name model_name %}">{{model_name}}</a></td>
18                     <td>ADD</td>
19                     <td>Change</td>
20                 </tr>
21                 {% endfor %}
22             </tbody>
23         </table>
24         {% endfor %}
25     </div>
26 
27 {% endblock %}
app_index.html

四、model_obj_list开发之生成列表跟过滤

  1、URL

    见上

  2、views视图

 1 def get_filter_result(admin_class,request):
 2     filter_conditions = {}
 3     for key,val in request.GET.items():
 4         # val为空时不过滤
 5         if val:
 6             filter_conditions[key] = val
 7     filtered_querysets = admin_class.model.objects.filter(**filter_conditions).all()
 8     return filtered_querysets,filter_conditions
 9 
10 @login_required()
11 def table_obj_list(request,app_name,model_name):
12     """取出指定model里的数据返回给前端"""
13     admin_class = site.enabled_admins[app_name][model_name]
14 
15     # 调用函数过滤处理,并返回
16     querysets,filter_conditions = get_filter_result(admin_class, request)
17     admin_class.filter_conditions = filter_conditions
18 
19     return render(request, 'kingadmin/table_obj_list.html',{
20         'querysets':querysets,
21         'admin_class':admin_class,
22     })
Kingadmin/views.py

  3、templates模块

 1 {% extends 'kingadmin/index.html' %}
 2 {# 导入标签模块 #}
 3 {% load kingadmin_tag %}  {# build_table_row' is not a registered tag library 重启即可 #}
 4 
 5 {% block right-content-container %}
 6     <h1 class="page-header">app</h1>
 7 
 8     <div>
 9         <form action="">
10             {% for filter_column in admin_class.list_filter %}
11                 {% build_filter_ele filter_column admin_class %}
12             {% endfor %}
13             <input type="submit" value="过滤">
14         </form>
15     </div>
16 
17     <div>
18         <table class="table table-striped">
19             <thead>
20                 <tr>
21                     {% for column in admin_class.list_display %}
22                     <th>{{column}}</th>
23                     {% endfor %}
24                 </tr>
25             </thead>
26             <tbody>
27                 {% for obj in querysets %}
28                 <tr>{% build_table_row obj admin_class %}</tr>
29                 {% endfor %}
30             </tbody>
31         </table>
32 
33     </div>
34 
35 {% endblock %}
tables_obj_list.html

  4、templatetags自定义

 1 from django.template import Library
 2 from django.utils.safestring import mark_safe
 3 import datetime
 4 
 5 register = Library()
 6 
 7 @register.simple_tag
 8 def build_table_row(obj,admin_class):
 9     """生成一条记录html element"""
10     ele = ''
11     for column_name in admin_class.list_display:
12         column_obj = admin_class.model._meta.get_field(column_name)
13         if column_obj.choices:  # 判断字段是否为choice
14             column_data = getattr(obj, 'get_%s_display' %column_name)()   # 获取choice的值
15         else:
16             column_data = getattr(obj, column_name)  # 反射
17         ele += '<td>%s</td>' % column_data
18     return mark_safe(ele)
19 
20 @register.simple_tag
21 def build_filter_ele(filter_column,admin_class):
22     """过滤"""
23     #获取字段对象
24     column_obj = admin_class.model._meta.get_field(filter_column)
25     try:
26         filter_select = '<select name=%s>' % filter_column
27         for choice in column_obj.get_choices():
28             selected = ''
29             # if filter_column in admin_class.filter_conditions:  # 当前字段被过滤了
30             if str(choice[0]) == admin_class.filter_conditions.get(filter_column):  # 当前值被选中
31                 selected = 'selected'
32             option = "<option value='%s' %s>%s</option>" % (choice[0],selected,choice[1])
33             filter_select += option
34     except AttributeError as e:
35         print('err',e)
36         filter_select = '<select name=%s__gte>' % filter_column
37         # 判断字段属性
38         if column_obj.get_internal_type() in ('DateField','DateTimeField'):
39             time_obj = datetime.datetime.now()
40             time_list = [
41                 ['--------------',''],
42                 ['Today',time_obj],
43                 ['Past 7 day',time_obj-datetime.timedelta(7)],
44                 ['This month',time_obj.replace(day=1)],
45                 ['Past 3 month',time_obj-datetime.timedelta(90)],
46                 ['This year',time_obj.replace(month=1,day=1)],
47                 ['Any day',''],
48             ]
49             for i in time_list:
50                 selected = ''
51                 time_to_str = '' if not i[1] else '%s-%s-%s' %(i[1].year,i[1].month,i[1].day)
52                 if time_to_str == admin_class.filter_conditions.get('%s__gte' %filter_column):  # 当前值被选中
53                     selected = 'selected'
54                 option = '<option value=%s %s>%s</option>' % (time_to_str,selected,i[0])
55                 filter_select += option
56 
57     filter_select += '</select>'
58     return mark_safe(filter_select)
kingadmin_tag.py

 

posted @ 2018-10-22 21:59  陆游憩  阅读(321)  评论(0编辑  收藏  举报