CRM项目(九)
现在该来添加前面提到的Action功能了,强大的它能干什么,先来体验一下原生admin中的效果。
1. 原生admin体验
- 默认的删除功能是可以进行批量删除的!


- 可以在后台进行自定义功能
在
CRM应用目录下的admin.py中添加:
from django.contrib import admin from CRM import models from django.shortcuts import render # Register your models here. #自定义操作 class CustomerAdmin(admin.ModelAdmin): list_display = ('name', 'id','qq','source','consultant','content','status','date') list_filter = ('source','consultant','date') search_fields = ('qq','name') raw_id_fields = ('consult_course',) filter_horizontal = ('tags',) list_editable = ('status',) #添加如下内容 actions = ("test_action", ) def test_action(self,request,arg2): print('test action:',self,request,arg2) return render(request,"king_admin/table_index.html")
效果图:

跳转到指定的页面:

2. 重写action
2.1基类中添加字段
第一件事还是跟以前一样,需要在基类中添加对应的字段选项:
king_admin_base.py文件中:
class ModelAdmin(object): list_display = [] list_filter = [] search_fields = [] ordering = None filter_horizontal = [] actions = [] #添加该字段 list_per_page = 10
2.2 添加默认的批量删除
我还要在基类中添加默认情况下的批量删除功能,这个同原生admin中定义的方式一样。需要在基类下面定义个批量删除功能的函数。
在king_admin_base.py文件中添加要定义的功能函数:
from django.shortcuts import render #创建基类 class ModelAdmin(object): list_display = [] list_filter = [] search_fields = [] ordering = None filter_horizontal = [] actions = ['delete_many_objects'] list_per_page = 10 def delete_many_objects(self, request, selected_objects): return render(request, 'king_admin/table_object_delete.html') ...
2.3 模板文件编写
2.3.1 模板文件中显示功能
要在模板文件中显示这个功能函数,我们必须在table_objs.html文件中添加,只需要简单的添加一些标签:
... <button type="SUBMIT" class="btn btn-success">search</button> </div> </form> </div> {# 添加action #} <div class="row" style="margin-top: 10px"> <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 }}">{{ action }}</option> {% endfor %} </select> </div> <div class="col-lg-1"> <button type="submit" class="btn " >Go</button> </div> </div> {#具体的表格内容展示 #} ...
显示效果如下:

有的朋友会问:你没有传admin_class变量?是的,这里没有必要再传了,因为在该模板文件中已经存在了!
2.3.2 模板中添加表单功能
上面只是简单的显示了功能,并没有实现具体的功能。然而实现具体的功能我们需要进行传递一些必要的值,传输这些值就需要表单组件来提供功能。
还是上面的代码,套一层表单标签即可:
</div>
</form>
</div>
{# 添加action #}
<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 }}">{{ action }}</option>
{% endfor %}
</select>
</div>
<div class="col-lg-1">
<button type="submit" class="btn">Go</button>
</div>
</form>
</div>
{#具体的表格内容展示 #}
2.3.3 中文显示功能
说到中文显示,我们就不得不用到自定义标签了。但在使用之前先来看看原生的admin是怎么实现中文显示的吧:
... def test_action(self,request,arg2): print('test action:',self,request,arg2) return render(request,"king_admin/table_index.html") test_action.short_description = '测试' #添加这行代码 ...
显示效果:

开始我们自己的中文显示吧,就为我们刚刚写到默认批量删除功能添加显示中文:
... class ModelAdmin(object): list_display = [] list_filter = [] search_fields = [] ordering = None filter_horizontal = [] actions = ['delete_many_objects'] list_per_page = 10 def delete_many_objects(self, request, queryset): return render(request, 'king_admin/table_object_delete.html') delete_many_objects.short_description = '批量删除' ...
模板文件修改如下:
{# 添加action #}
<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_name admin_class action %}</option>
{% endfor %}
</select>
</div>
在templates/tags.py文件中,添加的内容如下:
... <------------------------显示默认action中文-------------------------- @register.simple_tag def get_action_name(admin_class, action): action_func = getattr(admin_class, action) if hasattr(action_func, 'short_description'): return action_func.short_description else: return action
渲染后的效果:

2.4 视图函数
上面我们已经查不到将模板文件所需要的都已经编写完毕,接下来就是数据的收发,涉及到数据的收发我们必须要用到视图。这里是在table_objs.html文件基础上添加的功能,视图中,我们同样要使用它来接收来自该模板文件的数据请求。
2.4.1 模板文件的数据发送
前面刚刚建立了表单功能,向后台提交数据就需要使用POST方式进行,同时我们还要将那些选中的checkbox中的行id一同传送到后端。
在前面建立表单的时候,已经添加了传送方式和提交的函数:<form onsubmit="return ActionSubmit(this)" method="POST">,这里将具体的提交函数编写一下:
... function ActionSubmit(self) { var selected_ids = []; $("input[tag='object_checkbox']:checked").each(function () { selected_ids.push($(this).val()); }); var selected_action = $("#action_list").val(); if (selected_ids.length == 0){ alert("No object got selected!"); return; } if (!selected_action){ alert("No action got selected!"); } //添加隐藏标签,用来存储提交的数据key/value var selected_ids_ele = "<input name='selected_ids' type='hidden' value='" + selected_ids.toString() + "'>"; $(self).append(selected_ids_ele); return true; }
这些脚本同样放在该文件的最下面。
2.4.2 视图函数的数据接收
上面的数据已经发送,该接收数据了。接收数据的功能函数我们使用display_objects(request, app_name, table_name)即可,我们只需要添加几行代码:
... def display_objects(request, app_name, table_name): #获取自定义的admin_class admin_class = site.enabled_admins[app_name][table_name] #数据查询 #query_set = admin_class.model.objects.all() <------------------接收action数据---------------------------- if request.method == '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) #将action存储在请求体中便于调用 request._admin_action = action return action_func(admin_class, request, selected_objs) ...
2.5 编写具体批量删除功能
还记得之前编写的删除功能吗?这里我们要复用一下,在此基础上简单的添加一标签用来提交数据。
2.5.1 批量删除功能编写
继续填补之前编写的批量删除功能的架子,默认情况的GET请求页面获取,在king_admin_base.py中:
... def delete_many_objects(self, request, selected_objects): app_name = self.model._meta.app_label table_name = self.model._meta.model_name selected_ids = ','.join([str(i.id) for i in selected_objects]) return render(request, 'king_admin/table_object_delete.html',{'selected_objects': selected_objects, 'action': request._admin_action, 'selected_ids': selected_ids, 'app_name': app_name, 'table_name': table_name}) delete_many_objects.short_description = '批量删除'
2.5.2 复用编辑页面的删除功能主页面
在table_object_delete.html文件中修改如下:
{% extends 'king_admin/table_index.html' %}
{% load tags %}
{% block body-content %}
{% if not action %}
{# 显示映射关系 #}
{% display_object_related object_list %}
{# 表单提交 #}
<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">
<a class="btn btn-info" href="{% url 'king_admin:table_object_edit' app_name table_name object_id %}">No,Take me back</a>
</form>
{% else %}
{# 显示映射关系 #}
{% display_object_related selected_objects %}
{# 批量删除 #}
<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="{{ action }}" name="action"/>
<input type="hidden" value="{{ selected_ids }}" name="selected_ids"/>
<a class="btn btn-info" href="/king_admin/{{ app_name }}/{{ table_name }}/?page={{ get_page }}">No,Take me back</a>
</form>
{% endif %}
{% endblock %}
2.5.3 删除数据
上面完成了数据的发送与接收,最后剩下的就是数据的删除:
king_admin_base.py文件的函数修改:
... def delete_many_objects(self, request, selected_objects): app_name = self.model._meta.app_label table_name = self.model._meta.model_name selected_ids = ','.join([str(i.id) for i in selected_objects]) #添加如下判断 if request.method == 'POST': if request.POST.get('delete_confirm') == 'yes': selected_objects.delete() return redirect('/king_admin/{app_name}/{table_name}'.format(app_name=app_name, table_name=table_name)) return render(request, 'king_admin/table_object_delete.html',{'selected_objects': selected_objects, 'action': request._admin_action, 'selected_ids': selected_ids, 'app_name': app_name, 'table_name': table_name, 'get_page': request.GET.get('page')}) delete_many_objects.short_description = '批量删除' ...
效果查看:


Good!批量删除功能搞定了,同时也意味着action的告终。如果你想要实现其他功能,基本的流程就是这样的,仅供参考。
大致的思路如下:

未完待续。。。
原文:http://www.cnblogs.com/runner1/articles/6391070.html

浙公网安备 33010602011771号