项目一:CRM(客户关系管理系统)--9

Posted EagleSour

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目一:CRM(客户关系管理系统)--9相关的知识,希望对你有一定的参考价值。

现在该来添加前面提到的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的告终。如果你想要实现其他功能,基本的流程就是这样的,仅供参考。

大致的思路如下:

技术分享图片

 

以上是关于项目一:CRM(客户关系管理系统)--9的主要内容,如果未能解决你的问题,请参考以下文章

Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色

CRM客户关系管理系统商业项目

CRM

项目一:CRM(客户关系管理系统)--2

CRM客户关系管理系统商业项目视频课程

项目一:CRM(客户关系管理系统)--7