zoukankan      html  css  js  c++  java
  • Python CRM项目六

    自定义Django Admin的action

    在Django Admin中,可以通过action来自定义一些操作,其中默认的action的功能是选中多条数据来进行删除操作

    我们在king_admin中也可以通过开发类似的功能性组件来实现自定义action

    首先在king_admin中添加actions字段

    actions = ['delete_selected_objs',] #和django admin一样,添加默认删除选中的多条记录的方法

    在views视图中,获取前端页面传来的选中的记录id和action的函数名

      #post请求执行action操作
        if request.method == 'POST':
            selected_ids = request.POST.get('selected_ids')#获取选中记录的id
            action_name = request.POST.get('action')#获取函数名
            if selected_ids:
           #根据选中记录的id去数据库中获取记录 selected_objs
    = admin_class.model.objects.filter(id__in=selected_ids.split(',')) else: raise KeyError('没有数据')
         #如果在admin_class中找到了该函数,则获取该函数,然后将admin_class,request和查询的记录传递到king_admin.py中的函数
    if hasattr(admin_class,action_name): action_func = getattr(admin_class,action_name) request._action = action_name return action_func(admin_class,request,selected_objs)

    在king_admin.py中,获取这些参数,第一次调用时候,返回预删除页面,将值回填到预删除页面,当点击确认删除,此时delete_confrim值可获取到,

    并且执行删除操作,执行完毕跳转到展示页

     def delete_selected_objs(self,request,query_set):
            app_name = self.model._meta.app_label #获取app的名称
            model_name = self.model._meta.model_name #获取表名
            selected_ids = ','.join([str(i.id) for i in query_set]) #获取选中记录的id
            if request.POST.get('delete_confirm') == 'yes':
           #当在待删除页面,点击确认删除的时候,delete_confirm才会有值,第一次进入该方法时,这里的值为空  query_set.delete()
    return redirect('/king_admin//%s/%s/' % (app_name,model_name)) #返回到待删除页面,传递的参数分别是(要删除的记录,admin_class,app名称,表名,选中的id,和要调用的方法)
    #主要是为了点击确认删除时候,页面跳转到views中的方法,此时selected_id和action_name的值要回填,否则报错
    return render(request,'king_admin/table_delete.html',{'model_obj':query_set, 'admin_class':self, 'app_name':app_name, 'table_name':model_name, 'selected_ids':selected_ids, 'action':request._action})

    前端页面

    作用: 1.在下拉列表中展示可调用的action

             2.checkbox的多条数据删除和数据校验

    <div class="row">
                    <form method="POST" onsubmit="return submitAction(this)">{% csrf_token %}
                        <div class="col-lg-2">
                            <select name="action" id="action_list" class="form-control" style="margin-top:20px">
                                <option value="">-----</option>
                                {% for action in admin_class.actions %}
                                    <option value="{{ action }}">{% build_action_name admin_class action %}</option>
                                {% endfor %}
                            </select>
                        </div>
                        <div class="col-lg-2">
                            <button type="submit" class="btn" style="margin-top:20px;margin-left:-10px">执行</button>
                        </div>
                    </form>
    </div>
    <table class="table table-hover">
                    <thead>
                        <tr>
                            <th><input type="checkbox" onclick="checkAllToggle(this)"></th>
                            {% for column in admin_class.list_display %}
    {#                            动态展示表格中的数据,排序关键字,和筛选条件#}
                                {% build_table_header_column column orderby_key filter_conditions %}
                            {% endfor %}
                        </tr>
                    </thead>
                    <tbody>
    {#            <!--动态展示后端的表格中的数据--!>#}
                        {% for obj in query_sets %}
    
                            <tr>
                                <td><input tag="obj_check" type="checkbox" value="{{ obj.id }}"/></td>
                                {% bulid_table_row request obj admin_class %}
                            </tr>
                        {% endfor %}
                    </tbody>
    </table>

    js部分

    function checkAllToggle(ths){
                //复选框全选,反选
                if($(ths).prop('checked')){
                    $("input[tag='obj_check']").prop('checked',true);
                }
                else {
                    $("input[tag='obj_check']").prop('checked', false);
                }
            }
    
    
    function submitAction(ths){
                //后台提交action所要的数据
                selected_ids = [];
                //将复选框选中的值放到列表中
                $("input[tag='obj_check']:checked").each(function(){
                    selected_ids.push($(this).val());
                });
                //获取action的名字
                var select_action = $('#action_list').val();
                console.log(select_action)
                if(selected_ids.length == 0){
                    alert('没有选择数据');
                    return;
                }
                if(!select_action){
                    alert('没有选择方法');
                    return;
                }
    
                //添加已经选择的id,放到隐藏域中,一起提交到后台
                var selected_id_ele = "<input name='selected_ids' type='hidden' value='"+selected_ids.toString()+"'/>";
                $(ths).append(selected_id_ele);
                return true;
            }

    预删除页面展示

    在预删除页面,加入回填的参数,在点击确认删除时,获取king_admin中传递到前端的值,在把这些值第二次传递给后端的views中,此时views中会第二次调用

    king_admin中的action的方法,同时获取到delete_confirm的值,执行删除操作,删除完毕后跳转首页

    {% block container %}
    
        {% display_obj_related model_obj %}
    
        <form method="post">{% csrf_token %}
            <input type="submit" class="btn btn-danger" value="确认删除">
            <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 %}">返回</a>
        </form>
    
    {% endblock %}

    最后一步,可以通过在action中自定义显示的函数名

    class CustomerAdmin(BaseAdmin):
        list_display = ['qq','name','source','consultant','consult_course','date','status']
        list_filters = ['source','consultant','consult_course','status','date']
        search_fields = ['qq','name','consultant__name']
        list_per_page = 5
        ordering = 'id'
        filter_horizontal = ['tags',]
    #继承父类中的action,每个类自定义的action actions
    = ['delete_selected_objs','test',] def test(self,request,query_set): print('test...') #加上这条属性表示在action下拉框中展示此字段 test.display_name = '测试'

    在tags中渲染

    @register.simple_tag
    def build_action_name(admin_class,action):
        #获取admin_class的action对象
        action_func = getattr(admin_class,action)
    #如果有display_name就返回display_name的名称,否则就展示action字段
    return action_func.display_name if hasattr(action_func,'display_name') else action

    前端页面展示

    <select name="action" id="action_list" class="form-control" style="margin-top:20px">
        <option value="">-----</option>
        {% for action in admin_class.actions %}
    {# <!--自定义标签中去显示下拉框的名称--!>#}
    <option value="{{ action }}">{% build_action_name admin_class action %}</option> {% endfor %} </select>
  • 相关阅读:
    Nginx的configure各项中文说明
    nginx+keepalived高可用及双主模式
    nginx实现请求的负载均衡 + keepalived实现nginx的高可用
    Keepalived详细介绍简介
    keepalived vip漂移基本原理及选举算法
    keepalived脑裂问题查找
    计算机网络的三种通讯模式(单播,广播,组播)
    二层交换机、三层交换机、路由器
    Linux /var/log下的各种日志文件详解
    报文、帧、数据包等的区别
  • 原文地址:https://www.cnblogs.com/luhuajun/p/7879413.html
Copyright © 2011-2022 走看看