一、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()
==========================
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
==========================
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)
=========================
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() # 只实例化一次,后面的导入为调用对象
========================
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})
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 %}
四、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 })
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 %}
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)