参考:https://www.cnblogs.com/Eric15/articles/9247723.html

 kingadmin页面开发基于CRM开发,详情请参考上述链接


 

Kingadmin


前戏:目录

    

 

在CRM项目中:

01. 创建Kingadmin App:python manage.py startapp kingadmin

02. 创建static静态文件夹、templates文件夹,将需要的样式表、html页面分别移入static、templates文件夹中

03. perfect CRM中的setting设置:

INSTALLED_APPS:添加 “kingadmin” APP
TEMPLATES:添加 “kingadmin/templates” 路径
STATICFILES_DIRS:添加 “static” 路径

 

kingadmin 操作开始

1、kingadmin下的login、logout界面,参考crm写就可以了,需要注意的是:

 kingadmin中创建urls.py文件,操作:

# perfect CRM下的urls:
path('kingadmin/',include("kingadmin.urls")),

# kingadmin下的urls: (urls.py需创建)
from django.urls import path
from kingadmin import views

urlpatterns = [
    path('login/',views.acc_login),
    path('logout/',views.acc_logout,name='logout'),
]

 

2、kingadmin下的首页:

 urls:

1 re_path('^$',views.app_index,name='app_index'),

 views:

1 def app_index(request):
2     """kingadmin下的首页"""
3     return  render(request,"kingadmin/app_index.html")

 html:app_index.html

1 #继承于kingadmin下的index.html
2 
3 {% extends "index.html" %}
4 
5 {% block right-content-container %}
6 {% block Role_name %}
7     KingAdmin
8 {% endblock %}
9 {% endblock %}

 

 

3、kingadmin下的主页(类似admin主页)

(1) settings中需添加app:

    

(2) 生成app_setup.py文件:用于导入并执行各app下的kingadmin.py文件,如无kingadmin.py文件则跳过

 1 from django import conf
 2 
 3 def kingadmin_auto_discover():
 4     for app_name in conf.settings.INSTALLED_APPS:
 5         # 遍历setting配置中的各app,找到app下的'kingadmin.py',如有,则导入,如没有则报错:ImportError
 6         # mod = importlib.import_module(app_name, 'kingadmin')
 7         try:
 8             #try 找到各APP中的Kingadmin.py文件,没找到的pass处理 __import__ 等价于 importlib.import_module(app_name, 'kingadmin')
 9             mod =__import__("%s.kingadmin"%app_name)
10             # print(mod.kingadmin) # <module 'crm.kingadmin' from 'C:\\Users\\Administrator\\Desktop\\PerfectCRM\\crm\\kingadmin.py'>
11 
12         except ImportError:
13             pass

 

(3) 自创建kingadmin注册文件:sites.py

 1 from kingadmin.admin_base import BaseKingAdmin
 2 # BaseKingAdmi需另外创建
 3 
 4 class AdminSite(object):
 5     def __init__(self):
 6         self.enabled_admin = {}
 7 
 8 
 9     def register(self,model_class,admin_class=None):
10         """
11         注册表:
12         site.register(models.CustomerInfo,CustomerAdmin)
13         :param model_class: models.CustomerInfo
14         :param admin_class: CustomerAdmin
15         model_class._meta.app_label = models.CustomerInfo._meta.app_label :获取对应APP名称
16         model_class._meta.model_name = models.CustomerInfo._meta.model_name :获取对应表名称
17         """
18 
19         app_name = model_class._meta.app_label
20         model_name = model_class._meta.model_name
21 
22         if not admin_class: # 为了避免多个model共享同一个BaseKingAdmin内存对象
23             # 实例化BaseKingAdmin对象,每一次循环此语句都开辟一块新内存
24             admin_class = BaseKingAdmin()
25 
26         else:
27             # 实例化 CustomerAdmin 对象
28             admin_class = admin_class()
29 
30         admin_class.model = model_class # 把model_class赋值给了admin_class
31 
32         if app_name not in self.enabled_admin:
33             self.enabled_admin[app_name] = {}
34 
35         # enabled_admins中存的是字典(字典中套字典):crm:{ {'CustomerInfo':'CustomerAdmin'} , {'Role':'RoleAdmin'}}
36         # enabled_admins[crm][CustomerInfo] = CustomerAdmin
37         self.enabled_admin[app_name][model_name] = admin_class
38 
39 
40 site = AdminSite()
BaseKingAdmin:
1 class BaseKingAdmin(object):
2     pass

 

(4) 在各app中创建kingadmin.py文件:用于自定义kingadmin注册

 1 from kingadmin.sites import site
 2 from crm import models
 3 from kingadmin.admin_base import BaseKingAdmin
 4 
 5 
 6 print("crm kingadmin ...........")
 7 
 8 class CustomerAdmin(BaseKingAdmin):
 9     list_display = ['id','name','source','contact_type','contact','consultant','consult_content','status','date']
10     list_filter = ['source','consultant','status','date']
11     search_fields = ['contact','consultant__name']
12     #
13     # readonly_fields = ['status', 'contact']
14     # filter_horizontal = ['consult_courses', ]
15     #
16     # actions = ['change_status', ]
17 
18     # def change_status(self, request, querysets):
19     #     # print("kingadmin action:", self, request, querysets)
20     #     querysets.update(status=1)
21 
22 
23 # class CourseRecordAdmin(BaseKingAdmin):
24 #     actions = ['change_status', ]
25 
26 site.register(models.CustomerInfo,CustomerAdmin)
27 site.register(models.Role)
28 site.register(models.Menus)
29 site.register(models.Course)
30 site.register(models.ClassList)
31 # site.register(models.CourseRecord,CourseRecordAdmin)
32 site.register(models.StudyRecord)
33 site.register(models.UserProfile)
注册

 

(5)views:

1 from kingadmin import app_setup
2 from kingadmin.sites import site
3 
4 #导入各app中的kingadmin模块
5 app_setup.kingadmin_auto_discover()

 

(6) 页面app_index.html:

 1 {% extends 'kingadmin/index.html' %}
 2 
 3 
 4 {% block  right-content-container %}
 5     <h2 class="page-header">Kingadmin</h2>
 6     <div>
 7         <!-- 各APP及其表数据展示(body部分的右边展示栏)-->
 8         {% for app_name,app_tables in site.enabled_admins.items %}
 9             <table class="table table-striped table-hover">
10                 <thead>
11                 <tr>
12                     <th>{{ app_name }}</th>
13                 </tr>
14                 </thead>
15                 <tbody>
16                 {% for model_name in app_tables %}
17                     <tr>
18                         <td><a href="{% url 'table_obj_list' app_name model_name %}">{{ model_name }}</a></td>
19                         <td><a href="/kingadmin/{{ app_name }}/{{ model_name }}/add"><span class="glyphicon glyphicon-plus" aria-hidden="true" style="margin-right: 5px"></span>Add</a></td>
20                         <td><a href="/kingadmin/{{ app_name }}/{{ model_name }}"><span class="glyphicon glyphicon-pencil" aria-hidden="true" style="margin-right: 5px"></span>Change</a></td>
21                     </tr>
22                 {% endfor %}
23                 </tbody>
24 
25 
26             </table>
27 
28 
29 
30         {% endfor %}
31 
32     </div>
33 
34 
35 
36 
37 
38 
39 
40 {% endblock %}
app_index主页

 

 3、进入crm APP中的customerinfo表中,列出list_display中的数据 及过滤功能:

(1)在主页app_index.html设置可点击超链接

(2) 开发数据列表页:当用户点击crm下的customerinfo时,进入customerinfo数据页

 1. table_obj_list.html:

 1 {#显示表中各数据#}
 2     <table class="table table-striped">
 3         <thead>
 4         <tr>
 5             {% for column in admin_class.list_display %}
 6                 <th>{{ column }}</th>
 7 
 8             {% endfor %}
 9 
10         </tr>
11         </thead>
12         <tbody>
13             {% for obj in querysets %}
14                 <tr>
15 {#                <td><input row-select="true" type="checkbox" value="{{ obj.id }}"></td>#}
16                     {% build_table_row obj admin_class %}
17                 </tr>
18             {% endfor %}
19         </tbody>
20 
21 
22     </table>
模板页代码

 2. 自定义模板标签: 

1 """
2 templatetags包,用于创建自定义标签,再用于前端显示
3 自定义标签步骤: 1、在APP文件中创建 templatetags包(不是文件夹)
4                 2、在templatetags包中创建 kingadmin.py文件
5                 3、导入:from django.template import Library
6                 4、实例化:register = Library() 。注:命名必须‘register’,不能改
7 """
自定义标签补充

 

(3) 关于过滤、搜索、排序、分页等功能请点击下述链接↓:

  https://www.cnblogs.com/Eric15/articles/9270586.html

 


 

 5、 kingadmin下的增删改查:

 5-1. 查看 / 修改操作:

  urls:

1 re_path(r'^(\w+)/(\w+)/(\d+)/change/$',views.table_obj_change,name='table_obj_change'),
urls

  

  views:

 1 @login_required
 2 def table_obj_change(request,app_name,model_name,obj_id):
 3     """
 4     信息修改操作(页面)
 5     利用Django自带form表单操作
 6     """
 7     admin_class = site.enabled_admins[app_name][model_name]
 8     model_form = form_handle.create_dynamic_model_form(admin_class)
 9     obj = admin_class.model.objects.get(id=obj_id)
10     if request.method == 'GET':
11         # GET:查看当前页,返回当前对象的所有数据
12         form_obj = model_form(instance=obj)
13     else:
14         # POST: 修改当前页,获取数据并保存新数据
15         form_obj = model_form(instance=obj, data=request.POST)
16         if form_obj.is_valid():
17             form_obj.save()
18             return redirect("/kingadmin/%s/%s/" % (app_name, model_name))
19     # print("type--------------",type(form_obj))
20     return render(request, 'kingadmin/table_obj_change.html', locals())
views

  

  自定义form表单接收/返回数据(Django自带Form表单):与新增操作共享

 1 """
 2     动态生成form表单,动态展示各表中单个角色内的详细表单信息
 3     接收后台数据,根据数据返回或保存数据
 4 """
 5 
 6 
 7 from django.forms import ModelForm
 8 
 9 
10 def create_dynamic_model_form(admin_class,form_add=False):
11     """
12     根据传入admin_class,获取不同表信息,动态生成对应的modelform表单
13     form_add: False 默认是修改的表单,True时为添加
14     """
15 
16     class Meta:
17         model = admin_class.model
18         #所有字段都展示
19         fields = "__all__"
20         if not form_add:#change,如果是修改操作,不能修改的信息应该设置成只读项
21             exclude = admin_class.readonly_fields
22             admin_class.form_add = False #这是因为自始至终admin_class实例都是同一个,
23             # 这里修改属性为True是为了避免上一次添加调用将其改为了True
24         else: #add,如果是添加操作,没有只读项这回事
25             admin_class.form_add = True#返回给前端,判断是修改数据还是新增数据
26 
27 
28     def __new__(cls,*args,**kwargs):
29         """
30         Django中ModelForm表单生成都是在ModelForm的__new__方法中生成
31         要给通过ModelForm生成的表单添加自定义标签样式,需要在此方法中处理
32         base_fields----: 表单中所有信息,([('名称',对象),('名称',对象)...])OrderedDict([('name', <django.forms.fields.CharField object at 0x0000000004ACA4A8>), ('contact_type', <django.forms.fields.TypedChoiceField object at 0x0000000004ACA5C0>)....
33         """
34         for field_name in cls.base_fields: #获得每个字段的名称
35             # print('base_fields----:',cls.base_fields)
36             field_obj =cls.base_fields[field_name] #获取该字段名对应的对象
37             # 给该字段对象更新/增加class属性
38             field_obj.widget.attrs.update({'class':'form-control'})
39 
40         # 最后务必调用父类__new__方法
41         return ModelForm.__new__(cls)
42 
43 
44 
45     dynamic_form = type("DynamicModelForm",(ModelForm,),{'Meta':Meta,'__new__':__new__})
46     """
47     type("DynamicModelForm",(ModelForm,)
48     DynamicModelForm:类名
49     ModelForm:继承的类
50     {'Meta':Meta}:DynamicModelForm类的成员,可以是类、方法或其他
51     """
52     return dynamic_form #dynamic_form:是类,返回dynamic_form类  <class 'django.forms.widgets.DynamicModelForm'>
Django自带Form表单

 


 

   模板页面:内容继承于:kingadmin/table_obj_change_component.html 页面

 1 {% extends 'kingadmin/index.html' %}
 2 {% load kingadmin_tags %}
 3 
 4 
 5 {% block  right-content-container %}
 6 {#    <ol class="breadcrumb">#}
 7 {#        <li><a href="/kingadmin/">Home</a></li>#}
 8 {#        <li><a href="/kingadmin/{{ app_name }}">{{ app_name }}</a></li>#}
 9 {#        <li><a href="/kingadmin/{{ app_name }}/{{ model_name }}/">{% get_model_verbose_name admin_class %}</a></li>#}
10 {#        <li class="active">{{ form_obj.instance }}</li>#}
11 {#    </ol>#}
12     <h2 class="page-header">{% get_model_name admin_class %}</h2>
13     <h4 class="page-header">更改 {{ form_obj.instance }} 信息:</h4>
14 
15     <div>
16 
17         {% include 'kingadmin/table_obj_change_component.html' %}
18 
19     </div>
20 
21 {% endblock %}
查看or修改操作

 

  kingadmin/table_obj_change_component.html:用于修改或增加数据时,前端显示内容

 1 {% load kingadmin_tags %}
 2 
 3 
 4 <form class="form-horizontal" method="post"> {% csrf_token %}
 5     {{ form_obj.errors }}
 6     {% for field in form_obj %}
 7         <div class="form-group">
 8             <label class="col-sm-2 control-label">{{ field.label }}:</label>
 9             <div class="col-sm-10 ">
10                 {{ field }}
11                 <span style="color: red">{{ field.errors.0 }} </span>
12             </div>
13         </div>
14     {% endfor %}
15 
16 
17 {% if not admin_class.form_add %}   <!--如果这是修改表单-->
18         {% for field in admin_class.readonly_fields %}
19             <div class="form-group">
20                 <label class="col-sm-2 control-label">{{ field }}:</label>
21                 <div class="col-sm-10">
22                     <p style="margin-top: 7px">{% get_obj_field_val form_obj field %}</p>
23                 </div>
24             </div>
25         {% endfor %}
26     {% endif %}
27 
28     <div class="col-sm-offset-11 col-sm-2">
29         <button type="submit" class="btn btn-info">Save</button>
30     </div>
31 
32 </form>
新增与修改操作的继承模板

 

  查看 / 修改页面:

 

 5-2. 新增操作:

  urls:

1 re_path(r'^(\w+)/(\w+)/add/$',views.table_obj_add,name='table_obj_add'),
新增操作-路由

  

  views:

 1 @login_required
 2 def table_obj_add(request,app_name,model_name):
 3     """增加操作(页面)"""
 4     admin_class = site.enabled_admins[app_name][model_name]
 5     model_form = form_handle.create_dynamic_model_form(admin_class,form_add=True)
 6     if request.method == 'GET':
 7         # GET:查看当前页,返回当前对象的所有数据
 8         form_obj = model_form()
 9     else:
10         # POST: 修改当前页,获取数据并保存新数据
11         form_obj = model_form(data=request.POST)
12         if form_obj.is_valid():
13             form_obj.save()
14             return redirect("/kingadmin/%s/%s/" % (app_name, model_name))
15 
16     return render(request, 'kingadmin/table_obj_add.html', locals())
新增操作

 

   自定义form表单接收/返回数据(Django自带Form表单):同查看操作

 

  模板页面:内容继承于:kingadmin/table_obj_change_component.html 页面

 1 {% extends 'kingadmin/index.html' %}
 2 {% load kingadmin_tags %}
 3 
 4 
 5 {% block  right-content-container %}
 6 {#    <ol class="breadcrumb">#}
 7 {#        <li><a href="/kingadmin/">Home</a></li>#}
 8 {#        <li><a href="/kingadmin/{{ app_name }}">{{ app_name }}</a></li>#}
 9 {#        <li><a href="/kingadmin/{{ app_name }}/{{ model_name }}/">{% get_model_verbose_name admin_class %}</a></li>#}
10 {#        <li class="active">{{ form_obj.instance }}</li>#}
11 {#    </ol>#}
12     <h2 class="page-header">{% get_model_name admin_class %}</h2>
13     <h4 class="page-header">添加新客户信息:</h4>
14     dsggdh
15     <div>
16 
17         {% include 'kingadmin/table_obj_change_component.html' %}
18 
19     </div>
20 
21 {% endblock %}
新增

 

  新增页面:

 

PS:新增/修改操作下,关于多对多选择的操作,题中:咨询课程

关键词:kingadmin.py → class CustomerAdmin(BaseKingAdmin) 下的:filter_horizontal = ['consult_courses', ]

效果图:

 

模板HTML页面:

 1 <div class="col-sm-10">
 2                 {% if field.name in admin_class.filter_horizontal %}
 3                     <div class="col-lg-5 panel-default ">
 4                         <div class="panel-heading">课程咨询 :</div>
 5                         <div class="input-group">
 6                             <span class="glyphicon glyphicon-search input-group-addon"></span>
 7 
 8                             <input type="search" class="form-control panel-body" oninput="FuzzSearch(this)">
 9 {#                            <span class="glyphicon glyphicon-search input-group-addon"></span>#}
10                         </div>
11                         <select id="id_{{ field.name }}_from" multiple class="form-control panel-body selecting" style="height: 116px;">
12                             {% get_available_m2m_data field.name form_obj admin_class as available_m2m_data %}
13                             {% for obj in available_m2m_data %}
14                                 <option ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_to')"
15                                         value="{{ obj.id }}">{{ obj }}</option>
16                             {% endfor %}
17                         </select>
18                         <p><a onclick="MoveAllElements('id_{{ field.name }}_from','id_{{ field.name }}_to')">Choose
19                             All</a></p>
20                     </div>
21                     <div class="col-lg-5 panel-default">
22                         <div class="panel-heading">选中的课程 :</div>
23                         <select tag="selected_m2m" id="id_{{ field.name }}_to" multiple class="form-control"
24                                 name="{{ field.name }}" style="height: 150px;">
25                             {% get_selected_m2m_data field.name form_obj admin_class as selected_m2m_data %}
26                             {% for obj in selected_m2m_data %}
27                                 <option value="{{ obj.id }}"
28                                         ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_from')">{{ obj }}</option>
29                             {% endfor %}
30 
31                         </select>
32                         <p><a onclick="MoveAllElements('id_{{ field.name }}_to','id_{{ field.name }}_from')">Remove
33                             All</a></p>
34                     </div>
35                 {% else %}
36                     {{ field }}
37                 {% endif %}
38                 <span style="color: red">{{ field.errors.0 }} </span>
39             </div>
HTML

 

模板HTML下的js操作:

 function MoveSelectedOption(ele, target_id) :多选框内,双击内容实现左移右移

 function MoveAllElements(from_id, to_id) :点击 ‘Choose All‘   或   ‘Remove All’  ,实现数据全部左移或右移

 function FuzzSearch(ele) :模糊查询

 function FuzzSearch(ele) :当页面数据提交时,让‘选中的课程’处于已选状态,默认未选中,无此方法会报错(‘未填写数据’)

 1 function MoveSelectedOption(ele, target_id) {
 2     #左移右移
 3 
 4         var new_target_id = $(ele).parent().attr('id');
 5         <!--获得父类select的id值-->
 6         var option = "<option value='" + $(ele).val() + "'ondblclick=MoveSelectedOption(this,'" + new_target_id + "') >" + $(ele).text() + "</option>";
 7         $("#" + target_id).append(option);
 8         $(ele).remove();
 9 
10     }
function MoveSelectedOption(ele, target_id)
1     function MoveAllElements(from_id, to_id) {
2     #all左移或右移
3 
4         {#console.log( $("#"+from_id).children())#}
5         $("#" + from_id).children().each(function () { <!--拿到select下的子类option,循环option执行函数-->
6             MoveSelectedOption(this, to_id);
7         })
8     }
function MoveAllElements(from_id, to_id)
 1 function FuzzSearch(ele) { <!--模糊查询-->
 2 
 3         {#console.log($(ele).val())#}
 4         var search_text = $(ele).val().toUpperCase();
 5         <!--拿到搜索框中输入的文本(转大写形式)-->
 6 
 7         $('.selecting').children().each(function () {
 8             if ($(this).text().toUpperCase().search(search_text) != -1) {
 9                     $(this).show();
10                 } else {
11                     $(this).hide();
12                 }
13         });
14 
15     }
function FuzzSearch(ele)
1 function VerificationBeforeFormSubmit() {
2         <!--提交信息前,让select框中数据全选-->
3 
4         $("select[tag] option").prop('selected', true);
5 
6     }
function VerificationBeforeFormSubmit()

 

 

自定义tag标签生成:kingadmin_tags.py

 get_available_m2m_data :返回的是m2m字段关联表的所有数据

 1 @register.simple_tag
 2 def get_available_m2m_data(field_name,form_obj,admin_class):
 3     """
 4     返回的是m2m字段关联表的所有数据
 5     filter_horizontal = ['consult_courses', ]
 6     field_obj:拿到consult_courses字段的对象(一个对象)
 7     field_obj.related_model:拿到consult_courses关联的表对象
 8     field_obj.related_model.objects.all():获取关联表的所有数据(queryset对象,打印课程名称)
 9     set():集合
10     """
11 
12     field_obj = admin_class.model._meta.get_field(field_name)
13     # print("field_obj----:",field_obj)
14     obj_list = set(field_obj.related_model.objects.all())
15     # obj_list = field_obj.related_model.objects.all()
16 
17     if form_obj.instance.id:
18         selected_data = set(getattr(form_obj.instance ,field_name).all())
19 
20         return obj_list - selected_data
21     else:
22         return obj_list
def get_available_m2m_data

 

 

get_selected_m2m_data:返回已选的m2m数据
 1 @register.simple_tag
 2 def get_selected_m2m_data(field_name,form_obj,admin_class):
 3     """
 4     返回已选的m2m数据
 5     getattr(form_obj.instance ,field_name):field_name=consult_courses,  getattr('对象','名称'),名称如果是外键,则获得该对象中外键对应
 6                                             的表对象
 7     getattr(form_obj.instance ,field_name).all():获取该外键关联表内(属于该对象的)所有数据
 8     """
 9 
10     if form_obj.instance.id:
11         selected_data = getattr(form_obj.instance ,field_name).all()
12 
13         return selected_data
14 
15     else:
16         return []
def get_selected_m2m_data

 


 

  5-3、删除操作

  urls:

1 re_path(r'^(\w+)/(\w+)/(\d+)/delete/$', views.table_obj_delete, name="obj_delete"),
urls

 

  views:

1 @login_required
2 def table_obj_delete(request,app_name,model_name,obj_id):
3     """删除操作"""
4     admin_class = site.enabled_admins[app_name][model_name]
5     obj = admin_class.model.objects.get(id=obj_id)
6     if request.method == "POST":
7         obj.delete()
8         return redirect("/kingadmin/{app_name}/{model_name}/".format(app_name=app_name,model_name=model_name))
9     return render(request,'kingadmin/table_obj_delete.html',locals())
views

 

  模板HTML页面:

 1 {% extends 'kingadmin/index.html' %}
 2 {% load kingadmin_tags %}
 3 
 4 {% block  right-content-container %}
 5 
 6 
 7     <h4 class="page-header alert-danger">注意:以下与{{ obj }}相关联的数据都将被删除!</h4>
 8 
 9 <div>
10 
11 
12 
13 
14     {% display_all_related_objs obj as all_related_obj_eles %}
15     {{ all_related_obj_eles|safe }}
16 
17 
18 
19 <form method="post">{% csrf_token %}
20 
21 <input type="submit" class="btn btn-danger" value="确认删除">
22 
23 
24     <a href="/kingadmin/{{ app_name }}/{{ model_name }}/{{ obj_id }}/change" class="btn btn-info" >返回</a>
25 
26 </form>
27 
28 </div>
29 
30 {% endblock %}
table_obj_delete.html

 

   母模板:table_obj_change_component.html

1 # table_obj_change_component.html下添加下列数据:
2 
3 {% if form_obj.instance.id %}
4                     <div class="col-sm-2">
5                         <a class="btn btn-danger" href="{% url 'obj_delete' app_name model_name form_obj.instance.id %}">Delete</a>
6 
7                     </div>
8                 {% endif %}
table_obj_change_component.html

 

  自定义tag标签:kingadmin_tags.py:

    def display_all_related_objs:显示要被删除对象的所有关联对象

 1 # 删除操作
 2 @register.simple_tag
 3 def display_all_related_objs(obj):
 4     """
 5     显示要被删除对象的所有关联对象
 6     :param obj:
 7     :return:
 8     """
 9     ele = "<ul><b style='color:red'>%s</b>" % obj
10     # ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a></li>" %(obj._meta.app_label,
11     #                                                                  obj._meta.model_name,
12     #                                                                  obj.id,obj)
13     """
14     obj = admin_class.model.objects.get(id=obj_id)
15     obj._meta.related_objects:拿到obj被关联的所有一对一、多对一、多对多的表[ManyToMany、ManyToOne],多对一是指己方表被别的表关联
16     reversed_fk_obj.name:拿到主动关联表的表名(含有fk外键关联的)
17     getattr(obj,related_lookup_key).all() :getattr(obj,Role_set).all(),反向查关联表的所有关联的数据[queryset集合]
18     reversed_fk_obj.get_internal_type():判断表类型,ForeignKey、ManyToManyField
19     getattr(obj,related_lookup_key).all()= obj.Role_set.all()
20     """
21 
22     for reversed_fk_obj in obj._meta.related_objects:
23 
24         if reversed_fk_obj.get_internal_type() == "OneToOneField":  # 一对一或者一对多不需要操作,多对一、多对多需要下述操作
25             continue
26         else:
27             related_table_name =  reversed_fk_obj.name
28             related_lookup_key = "%s_set" % related_table_name
29             related_objs = getattr(obj,related_lookup_key).all() #反向查所有关联的数据
30             ele += "<li>%s<ul> "% related_table_name
31 
32         # if reversed_fk_obj.get_internal_type() == "OneToOneField":  # 一对一或者一对多不需要操作,多对一、多对多需要下述操作
33 
34 
35             if reversed_fk_obj.get_internal_type() == "ManyToManyField":  # 不需要深入查找
36                 for i in related_objs:
37                     ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a> 记录里与[%s]相关的的数据将被删除</li>" \
38                         % (i._meta.app_label,i._meta.model_name,i.id,i,obj)
39             else:
40                 for i in related_objs:
41                     #ele += "<li>%s--</li>" %i
42                     ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a></li>" %(i._meta.app_label,
43                                                                                  i._meta.model_name,
44                                                                                  i.id,i)
45                     ele += display_all_related_objs(i)
46 
47             ele += "</ul></li>"
48 
49         ele += "</ul>"
50 
51     return ele
def display_all_related_objs

 

 


 

  5-4、kingadmin下的action功能开发:

 

 kingadmin.py:自定义action方法:处理选中的数据

1 # 添加至:class CustomerAdmin(BaseKingAdmin)中
2 actions = ['change_status', ]
3 
4     def change_status(self, request, querysets):
5         # print("kingadmin action: TEST……", self, request, querysets)
6         print("kingadmin action: 更改选中数据状态!")
7         # querysets.update(status=1)
class CustomerAdmin(BaseKingAdmin):

 admin_base.py:自定义action方法:批量删除操作

 1 class BaseKingAdmin(object):
 2     def __init__(self):
 3         self.actions.extend(self.default_actions)
 4 
 5     default_actions = ['delete_selected_objs']
 6     actions = []
 7 
 8 
 9     def delete_selected_objs(self, request, querysets):
10 
11         print("action:这是删除操作,请谨慎处理!")
class BaseKingAdmin(object):

 

 

 views:

  在table_obj_list函数中添加下列内容:映射上述自定义方法

 1 # 用于kingadmin下action行为所做操作
 2     if request.method == "POST":
 3         # print(request.POST)
 4         selected_action = request.POST.get('action')
 5         selected_ids = json.loads(request.POST.get('selected_ids'))
 6         # print(selected_action,selected_ids)
 7         if not selected_action:  # 如果有action参数,代表这是一个正常的action,如果没有,代表可能是一个删除动作
 8             if selected_ids:  # 这些选中的数据都要被删除
 9                 admin_class.model.objects.filter(id__in=selected_ids).delete()
10         else:  # 走action流程
11             selected_objs = admin_class.model.objects.filter(id__in=selected_ids)
12 
13             admin_action_func = getattr(admin_class, selected_action)
14             response = admin_action_func(request, selected_objs)
15             # response = admin_action_func(request,selected_objs)
16             if response:
17                 return response
def table_obj_list(request,app_name,model_name):

 

 

 模板HTML页面:

  在table_obj_list.html中某个位置添加下列代码:

 1 {# kingadmin action 操作      #}
 2     <form onsubmit="return ActionCheck(this)" method="post">{% csrf_token %}
 3             <div class="row" style="margin-top:5px">
 4                 <div class="col-lg-3">
 5                     <select class="form-control" name="action" >
 6                             <option value="">---------</option>
 7                          {% for action in admin_class.actions %}
 8                             <option value="{{ action }}">{{ action }}</option>
 9                         {% endfor %}
10                     </select>
11                 </div>
12                 <div>
13                     <input type="submit" value="GO" style="margin-top: 4px">
14 
15                 </div>
16             </div>
17 
18         </form>
table_obj_list.html

 

 

  在table_obj_list.html中最后添加下列js操作:

   function SelectAllObjs(ele):点击全选或全不选

1 function SelectAllObjs(ele) {
2 
3     if ($(ele).prop('checked')){
4         $('input[row-select]').prop('checked',true)
5 
6     }else {
7         $('input[row-select]').prop('checked',false)
8     }
function SelectAllObjs(ele)

 

   function ActionCheck(ele):获取数据后生成标签提供给后台使用

 1 function ActionCheck(ele){
 2     var selected_action = $("select[name='action']").val();
 3     var selected_objs = $("input[row-select]").filter(":checked");//找到已选数据(一条或多条)
 4     {#console.log($("select[name='action']").val())#}
 5     if (!selected_action){ //action框未选择方法
 6         alert("no action selected!");
 7         return false
 8     }
 9     if (selected_objs.length == 0 ){  //没有选中数据
10         alert("no object selected!");
11         return false
12     }else {
13         //生成一个标签,放到form里
14 
15         var selected_ids = [];
16         $.each(selected_objs,function () {  //循环selected_objs数据
17             console.log($(this) );
18             selected_ids.push($(this).val())
19         });
20         console.log(selected_ids);
21         var input_ele = "<input type='hidden' name='selected_ids' value=" + JSON.stringify(selected_ids) + ">"
22 
23         $(ele).append(input_ele);
24     }
function ActionCheck(ele)

 

 

 

 

     

 

 

 



 

 

 

 

 

 

 

 

 

 

 

posted on 2018-06-30 17:49  Eric_nan  阅读(214)  评论(0编辑  收藏  举报