现在该来添加前面提到的Action
功能了,强大的它能干什么,先来体验一下原生admin
中的效果。
1. 原生admin体验
默认的删除功能是可以进行批量删除的!
可以在后台进行自定义功能
在CRM
应用目录下的admin.py
中添加:
1 from django.contrib import admin 2 from CRM import models 3 from django.shortcuts import render 4 # Register your models here. 5 6 #自定义操作 7 class CustomerAdmin(admin.ModelAdmin): 8 list_display = (‘name‘, ‘id‘,‘qq‘,‘source‘,‘consultant‘,‘content‘,‘status‘,‘date‘) 9 list_filter = (‘source‘,‘consultant‘,‘date‘) 10 search_fields = (‘qq‘,‘name‘) 11 raw_id_fields = (‘consult_course‘,) 12 filter_horizontal = (‘tags‘,) 13 list_editable = (‘status‘,) 14 #添加如下内容 15 actions = ("test_action", ) 16 17 def test_action(self,request,arg2): 18 print(‘test action:‘,self,request,arg2) 19 return render(request,"king_admin/table_index.html")
效果图:
跳转到指定的页面:
2. 重写action
2.1基类中添加字段
第一件事还是跟以前一样,需要在基类中添加对应的字段选项:
king_admin_base.py
文件中:
1 class ModelAdmin(object): 2 list_display = [] 3 list_filter = [] 4 search_fields = [] 5 ordering = None 6 filter_horizontal = [] 7 actions = [] #添加该字段 8 list_per_page = 10
2.2 添加默认的批量删除
我还要在基类中添加默认情况下的批量删除功能,这个同原生admin
中定义的方式一样。需要在基类下面定义个批量删除功能的函数。
在king_admin_base.py
文件中添加要定义的功能函数:
1 from django.shortcuts import render 2 3 #创建基类 4 class ModelAdmin(object): 5 list_display = [] 6 list_filter = [] 7 search_fields = [] 8 ordering = None 9 filter_horizontal = [] 10 actions = [‘delete_many_objects‘] 11 list_per_page = 10 12 13 14 def delete_many_objects(self, request, selected_objects): 15 return render(request, ‘king_admin/table_object_delete.html‘) 16 17 ...
2.3 模板文件编写
2.3.1 模板文件中显示功能
要在模板文件中显示这个功能函数,我们必须在table_objs.html
文件中添加,只需要简单的添加一些标签:
1 ... 2 3 <button type="SUBMIT" class="btn btn-success">search</button> 4 </div> 5 </form> 6 </div> 7 {# 添加action #} 8 <div class="row" style="margin-top: 10px"> 9 <div class="col-lg-2"> 10 <select id="action_list" name="action" class="form-control" style="margin-left:15px"> 11 <option value="">---------</option> 12 {% for action in admin_class.actions %} 13 <option value="{{ action }}">{{ action }}</option> 14 {% endfor %} 15 </select> 16 </div> 17 <div class="col-lg-1"> 18 <button type="submit" class="btn " >Go</button> 19 </div> 20 </div> 21 {#具体的表格内容展示 #} 22 23 ...
显示效果如下:
有的朋友会问:你没有传admin_class
变量?是的,这里没有必要再传了,因为在该模板文件中已经存在了!
2.3.2 模板中添加表单功能
上面只是简单的显示了功能,并没有实现具体的功能。然而实现具体的功能我们需要进行传递一些必要的值,传输这些值就需要表单组件来提供功能。
还是上面的代码,套一层表单标签即可:
1 </div> 2 </form> 3 </div> 4 {# 添加action #} 5 <div class="row" style="margin-top: 10px"> 6 <form onsubmit="return ActionSubmit(this)" method="POST"> 7 {% csrf_token %} 8 <div class="col-lg-2"> 9 <select id="action_list" name="action" class="form-control" style="margin-left:15px"> 10 <option value="">---------</option> 11 {% for action in admin_class.actions %} 12 <option value="{{ action }}">{{ action }}</option> 13 {% endfor %} 14 </select> 15 </div> 16 <div class="col-lg-1"> 17 <button type="submit" class="btn">Go</button> 18 </div> 19 </form> 20 </div> 21 {#具体的表格内容展示 #}
2.3.3 中文显示功能
说到中文显示,我们就不得不用到自定义标签了。但在使用之前先来看看原生的admin
是怎么实现中文显示的吧:
1 ... 2 3 def test_action(self,request,arg2): 4 print(‘test action:‘,self,request,arg2) 5 return render(request,"king_admin/table_index.html") 6 test_action.short_description = ‘测试‘ #添加这行代码 7 8 ...
显示效果:
开始我们自己的中文显示吧,就为我们刚刚写到默认批量删除功能添加显示中文:
1 ... 2 class ModelAdmin(object): 3 list_display = [] 4 list_filter = [] 5 search_fields = [] 6 ordering = None 7 filter_horizontal = [] 8 actions = [‘delete_many_objects‘] 9 list_per_page = 10 10 11 12 def delete_many_objects(self, request, queryset): 13 return render(request, ‘king_admin/table_object_delete.html‘) 14 delete_many_objects.short_description = ‘批量删除‘ 15 ...
模板文件修改如下:
1 {# 添加action #} 2 <div class="row" style="margin-top: 10px"> 3 <form onsubmit="return ActionSubmit(this)" method="POST"> 4 {% csrf_token %} 5 <div class="col-lg-2"> 6 <select id="action_list" name="action" class="form-control" style="margin-left:15px"> 7 <option value="">---------</option> 8 {% for action in admin_class.actions %} 9 <option value="{{ action }}">{% get_action_name admin_class action %}</option> 10 {% endfor %} 11 </select> 12 </div>
在templates/tags.py
文件中,添加的内容如下:
1 ... 2 3 <------------------------显示默认action中文-------------------------- 4 @register.simple_tag 5 def get_action_name(admin_class, action): 6 action_func = getattr(admin_class, action) 7 if hasattr(action_func, ‘short_description‘): 8 return action_func.short_description 9 else: 10 return action
渲染后的效果:
2.4 视图函数
上面我们已经查不到将模板文件所需要的都已经编写完毕,接下来就是数据的收发,涉及到数据的收发我们必须要用到视图。这里是在table_objs.html
文件基础上添加的功能,视图中,我们同样要使用它来接收来自该模板文件的数据请求。
2.4.1 模板文件的数据发送
前面刚刚建立了表单功能,向后台提交数据就需要使用POST
方式进行,同时我们还要将那些选中的checkbox
中的行id
一同传送到后端。
在前面建立表单的时候,已经添加了传送方式和提交的函数:<form onsubmit="return ActionSubmit(this)" method="POST">
,这里将具体的提交函数编写一下:
1 ... 2 3 function ActionSubmit(self) { 4 var selected_ids = []; 5 $("input[tag=‘object_checkbox‘]:checked").each(function () { 6 selected_ids.push($(this).val()); 7 }); 8 var selected_action = $("#action_list").val(); 9 if (selected_ids.length == 0){ 10 alert("No object got selected!"); 11 return; 12 } 13 if (!selected_action){ 14 alert("No action got selected!"); 15 } 16 //添加隐藏标签,用来存储提交的数据key/value 17 var selected_ids_ele = "<input name=‘selected_ids‘ type=‘hidden‘ value=‘" + selected_ids.toString() + "‘>"; 18 $(self).append(selected_ids_ele); 19 return true; 20 }
这些脚本同样放在该文件的最下面。
2.4.2 视图函数的数据接收
上面的数据已经发送,该接收数据了。接收数据的功能函数我们使用display_objects(request, app_name, table_name)
即可,我们只需要添加几行代码:
1 ... 2 3 def display_objects(request, app_name, table_name): 4 #获取自定义的admin_class 5 admin_class = site.enabled_admins[app_name][table_name] 6 #数据查询 7 #query_set = admin_class.model.objects.all() 8 9 <------------------接收action数据---------------------------- 10 if request.method == ‘POST‘: 11 #获取提交的数据 12 selected_ids = request.POST.get("selected_ids") 13 action = request.POST.get("action") 14 #后台判断 15 if selected_ids: 16 selected_objs = admin_class.model.objects.filter(id__in=selected_ids.split(‘,‘)) 17 else: 18 raise KeyError("No object selected.") 19 if hasattr(admin_class, action): 20 action_func = getattr(admin_class, action) 21 #将action存储在请求体中便于调用 22 request._admin_action = action 23 return action_func(admin_class, request, selected_objs) 24 25 ...
2.5 编写具体批量删除功能
还记得之前编写的删除功能吗?这里我们要复用一下,在此基础上简单的添加一标签用来提交数据。
2.5.1 批量删除功能编写
继续填补之前编写的批量删除功能的架子,默认情况的GET
请求页面获取,在king_admin_base.py
中:
1 ... 2 def delete_many_objects(self, request, selected_objects): 3 app_name = self.model._meta.app_label 4 table_name = self.model._meta.model_name 5 selected_ids = ‘,‘.join([str(i.id) for i in selected_objects]) 6 return render(request, ‘king_admin/table_object_delete.html‘,{‘selected_objects‘: selected_objects, 7 ‘action‘: request._admin_action, 8 ‘selected_ids‘: selected_ids, 9 ‘app_name‘: app_name, 10 ‘table_name‘: table_name}) 11 delete_many_objects.short_description = ‘批量删除‘
2.5.2 复用编辑页面的删除功能主页面
在table_object_delete.html
文件中修改如下:
1 {% extends ‘king_admin/table_index.html‘ %} 2 {% load tags %} 3 4 {% block body-content %} 5 6 {% if not action %} 7 {# 显示映射关系 #} 8 {% display_object_related object_list %} 9 {# 表单提交 #} 10 <form method="post"> 11 {% csrf_token %} 12 <input type="submit" class="btn btn-danger" value="Yes,I‘m sure"> 13 <input type="hidden" value="yes" name="delete_confirm"> 14 <a class="btn btn-info" href="{% url ‘king_admin:table_object_edit‘ app_name table_name object_id %}">No,Take me back</a> 15 </form> 16 {% else %} 17 {# 显示映射关系 #} 18 {% display_object_related selected_objects %} 19 {# 批量删除 #} 20 <form method="post"> 21 {% csrf_token %} 22 <input type="submit" class="btn btn-danger" value="Yes,I‘m sure"> 23 <input type="hidden" value="yes" name="delete_confirm"> 24 <input type="hidden" value="{{ action }}" name="action"/> 25 <input type="hidden" value="{{ selected_ids }}" name="selected_ids"/> 26 <a class="btn btn-info" href="/king_admin/{{ app_name }}/{{ table_name }}/?page={{ get_page }}">No,Take me back</a> 27 </form> 28 {% endif %} 29 {% endblock %}
2.5.3 删除数据
上面完成了数据的发送与接收,最后剩下的就是数据的删除:
king_admin_base.py
文件的函数修改:
1 ... 2 def delete_many_objects(self, request, selected_objects): 3 app_name = self.model._meta.app_label 4 table_name = self.model._meta.model_name 5 selected_ids = ‘,‘.join([str(i.id) for i in selected_objects]) 6 #添加如下判断 7 if request.method == ‘POST‘: 8 if request.POST.get(‘delete_confirm‘) == ‘yes‘: 9 selected_objects.delete() 10 return redirect(‘/king_admin/{app_name}/{table_name}‘.format(app_name=app_name, 11 table_name=table_name)) 12 return render(request, ‘king_admin/table_object_delete.html‘,{‘selected_objects‘: selected_objects, 13 ‘action‘: request._admin_action, 14 ‘selected_ids‘: selected_ids, 15 ‘app_name‘: app_name, 16 ‘table_name‘: table_name, 17 ‘get_page‘: request.GET.get(‘page‘)}) 18 delete_many_objects.short_description = ‘批量删除‘ 19 20 ...
效果查看:
Good!批量删除功能搞定了,同时也意味着action
的告终。如果你想要实现其他功能,基本的流程就是这样的,仅供参考。
大致的思路如下: