11-crm项目-kingadmin,列表页actions功能开发
如果实现action的功能:
前端:
1,前端要加一个入口,可以选择某一个action,并且执行,
2,前端需要给每一个数据都增加一个复选框,增加js能选中批量操作的数据,
注意只是选择本页的,不是全部的,
怎么把选中的数据传到后台处理呢???
后端:
3,执行之后后端需要有处理函数
4,要做成可配置的,在基类里面做一个配置入口,
#############
在所有数据前面加一个复选框,
<table class="table table-hover"> <thead> <tr> <th style="width: 35px"><input type="checkbox" onclick="CheckAllToggle(this)" ></th> {% for column in admin_class.list_display %} {% build_table_header_column column orderby_key filter_condtions admin_class%} {% endfor %} </tr> </thead> <tfoot> <tr> <td></td> <td>总计{{ query_sets.paginator.count }}条</td></tr> </tfoot> <tbody> {# {% get_query_sets admin_class as query_sets %}#} {% for obj in query_sets %} <tr> <td ><input tag="obj_checkbox" type="checkbox" value="{{ obj.id }}"></td> {% build_table_row request obj admin_class %} </tr> {% endfor %} </tbody> </table>
增加action的操作入口:
<div class="row" style="margin-top: 10px"> <form onsubmit="return ActionSubmit(this)" method="POST">{% csrf_token %}
---把这个action放到了表单里面,post方式,this就是这个表单, <div class="col-lg-2"> <select id="action_list" name="action" class="form-control" style="margin-left:15px"> <option value="">---------</option> {% for action in admin_class.actions %} <option value="{{ action }}">{% get_action_verbose_name admin_class action %}</option> {% endfor %} </select> </div> <div class="col-lg-1" > <button type="submit" class="btn " >Go</button> </div> </form> </div>
对应的tag
@register.simple_tag def get_action_verbose_name(admin_class,action): action_func = getattr(admin_class,action) return action_func.display_name if hasattr(action_func,'display_name') else action
对应的js
<script> function CheckAllToggle(ele){ if ( $(ele).prop("checked")){ $("input[tag='obj_checkbox']").prop("checked",true); }else { $("input[tag='obj_checkbox']").prop("checked",false); } } function ActionSubmit(form_ele) { var selected_ids = []; $("input[tag='obj_checkbox']:checked").each(function () { ----"input[tag='obj_checkbox']:checked"这是取到了选中数据 selected_ids.push($(this).val()); ----这是把所有的值放到这个列表, }) var selected_action = $("#action_list").val(); console.log(selected_ids) console.log(selected_action) if (selected_ids.length == 0){ alert("No object got selected!"); return } if (!selected_action ){ alert("No action got selected!"); } //start submit var selected_ids_ele = "<input name='selected_ids' type='hidden' value='" + selected_ids.toString() + "' >" $(form_ele).append(selected_ids_ele); ---selected_ids这是所有选中的数据的id,放到表单里面,post提交, return true; } </script>
前端提交了,是提交到了当前页,这是列表页,
需要加一个处理,
@login_required def display_table_objs(request,app_name,table_name): print("-->",app_name,table_name) # 这是通过url取到的, #models_module = importlib.import_module('%s.models'%(app_name)) #model_obj = getattr(models_module,table_name) admin_class = king_admin.enabled_admins[app_name][table_name] #admin_class = king_admin.enabled_admins[crm][userprofile] if request.method == "POST": #action 来了 print(request.POST) selected_ids = request.POST.get("selected_ids") action = request.POST.get("action") if selected_ids: selected_objs = admin_class.model.objects.filter(id__in=selected_ids.split(',')) else: raise KeyError("No object selected.") if hasattr(admin_class,action): action_func = getattr(admin_class,action) request._admin_action = action return action_func(admin_class,request,selected_objs) ----这是调用函数了,然后你就可以在函数里面想干什么就干什么了, #object_list = admin_class.model.objects.all() object_list,filter_condtions = table_filter(request,admin_class) #过滤后的结果 object_list = table_search(request,admin_class,object_list) # 查询后的结果 object_list,orderby_key = table_sort(request, admin_class, object_list) #排序后的结果 print("orderby key ", orderby_key) paginator = Paginator(object_list, admin_class.list_per_page) # 分页 page = request.GET.get('page') try: query_sets = paginator.page(page) except PageNotAnInteger: # If page is not an integer, deliver first page. query_sets = paginator.page(1) except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. query_sets = paginator.page(paginator.num_pages) return render(request,"king_admin/table_objs.html",{"admin_class":admin_class, "query_sets":query_sets, "filter_condtions":filter_condtions, "orderby_key":orderby_key, "previous_orderby": request.GET.get("o",''), "search_text":request.GET.get('_q','')})
加一个删除的action,
class BaseAdmin(object): list_display = [] list_filters = [] search_fields = [] list_per_page = 20 ordering = None filter_horizontal = [] readonly_fields = [] actions = ["delete_selected_objs",] readonly_table = False modelform_exclude_fields = [] def delete_selected_objs(self,request,querysets): app_name = self.model._meta.app_label table_name = self.model._meta.model_name print("--->delete_selected_objs",self,request,querysets) if self.readonly_table: errors = {"readonly_table": "This table is readonly ,cannot be deleted or modified!" } else: errors = {} if request.POST.get("delete_confirm") == "yes": -----这是处理提交,其他都是处理get请求的, if not self.readonly_table: querysets.delete() return redirect("/king_admin/%s/%s/" % (app_name,table_name)) selected_ids = ','.join([str(i.id) for i in querysets]) ---这是获取到所有的要删除的id。 return render(request,"king_admin/table_obj_delete.html",{"objs":querysets, -----这是返回到了删除页面了,注意传递的字段, "admin_class":self, "app_name": app_name, "table_name": table_name, "selected_ids":selected_ids, "action":request._admin_action, ---把这些参数都传递到删除页面, "errors":errors })
删除页面需要修改:
{% extends 'king_admin/table_index.html' %} {% load tags %} {% block container %} {% display_obj_related objs %} <ul style="color: red"> {% for k,v in errors.items %} <li>{{ k }}:{{ v }}</li> {% endfor %} </ul> <form method="post">{% csrf_token %} <input type="submit" class="btn btn-danger" value="Yes,I'm sure"> <input type="hidden" value="yes" name="delete_confirm"> ----这是添加的隐藏域, <input type="hidden" value="{{ selected_ids }}" name="selected_ids"> <input type="hidden" value="{{ action }}" name="action"> <a class="btn btn-info" href="{% url 'table_objs' app_name table_name %}">No,Take me back</a> </form> {% endblock %}
返回到列表页的时候,有两种post,一个是action的post,一个是删除点击确认之后的post返回列表页,
但是现在列表页的处理函数只有一个post,如何能解决两个post的请求?
在action函数里面做判断,在删除页面加一个删除标识,
点击删除的action之后,是调用action函数,然后函数里面是跳转到删除页面,然后删除页面提交处理post,
可以再加action了
def test(self,request,querysets): print("in test",) test.display_name = "测试动作"
让前端显示中文,
<div class="row" style="margin-top: 10px"> <form onsubmit="return ActionSubmit(this)" method="POST">{% csrf_token %} <div class="col-lg-2"> <select id="action_list" name="action" class="form-control" style="margin-left:15px"> <option value="">---------</option> {% for action in admin_class.actions %} <option value="{{ action }}">{% get_action_verbose_name admin_class action %}</option> {% endfor %} </select> </div> <div class="col-lg-1" > <button type="submit" class="btn " >Go</button> </div> </form> </div>
tag:如果有displayname就返回这个,否则就返回action,
@register.simple_tag def get_action_verbose_name(admin_class,action): action_func = getattr(admin_class,action) return action_func.display_name if hasattr(action_func,'display_name') else action
#################
技术改变命运