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>
              {#具体的表格内容展示 #}
View Code
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 = '批量删除'

...
View Code

效果查看:

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

大致的思路如下:

未完待续。。。

 

原文:http://www.cnblogs.com/runner1/articles/6391070.html

posted @ 2018-02-11 18:18  dion至君  阅读(123)  评论(0)    收藏  举报