Python Web开发学习

【CRM客户关系管理】22.action功能开发,执行actio

2018-12-23  本文已影响0人  吾星喵

执行actions功能

form中增加提交函数

修改form中提交执行的操作

<form method="post" onsubmit="ActionCheck(this)">
    <div class="row">
        <div class="col-md-3">
            <select class="form-control" name="action">
                <option value="">-------</option>
                {% for action in admin_class.actions %}
                    <option value="{{ action }}">{{ action }}</option>
                {% endfor %}
            </select>
        </div>
        {% csrf_token %}
        <div class="col-md-2">
            <input type="submit" value="执行" class="btn btn-primary">
        </div>
    </div>
</form>

使用js来向form增加数据选项

table_detail.html模板的所有内容如下,包含js函数ActionCheck(ele)

{% extends 'djadmin/base.html' %}

{% load djadmin_tags %}

{% block title %}
    数据表详情 - 后台管理
{% endblock %}

{% block content %}
    <h1 class="page-header">应用 - {{ app_name }} - {{ model_name }}</h1>
    <a href="{% url 'djadmin:table_add' app_name model_name %}"><button class="btn btn-primary">添加</button></a>
    {#  queryset #}
    {% if admin_class.list_filter %}
        <p>
            <form class="navbar-form navbar-left">
                {% for filter_field in admin_class.list_filter %}
                    {% build_option_filter filter_field admin_class %}
                {% endfor %}
                <button type="submit" class="btn btn-primary">过滤</button>
            </form>
        </p>
    {% endif %}

    <form method="post" onsubmit="ActionCheck(this)">
        <div class="row">
            <div class="col-md-3">
                <select class="form-control" name="action">
                    <option value="">-------</option>
                    {% for action in admin_class.actions %}
                        <option value="{{ action }}">{{ action }}</option>
                    {% endfor %}
                </select>
            </div>
            {% csrf_token %}
            <div class="col-md-2">
                <input type="submit" value="执行" class="btn btn-primary">
            </div>
        </div>
    </form>

    <table class="table table-striped">
        <thead>
            <tr>
                <th><input type="checkbox" onclick="SelectALLObjs(this)"></th>
                {% if admin_class.list_display %}
                    {% for display_field in admin_class.list_display %}
                        <th>
                            <a href="?_order={% get_sorted_data display_field current_order_field forloop.counter0 %}{% render_filter_args admin_class %}">
                                {{ display_field }} {% get_sorted_arrow display_field current_order_field forloop.counter0 %}
                            </a>
                        </th>
                    {% endfor %}
                {% else %}
                    {% build_table_head_name admin_class %}
                {% endif %}
                <th>操作</th>
                <!--
                {% build_table_head_name admin_class %}
                -->
            </tr>
        </thead>
        <tbody>
            {% for obj in queryset %}
                <tr>
                    <td><input row-select="true" type="checkbox" value="{{ obj.id }}"></td>
                    {% build_table_body obj admin_class %}
                    <td><a href="{% url 'djadmin:table_delete' app_name model_name obj.id %}">删除</a></td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

    <div>
        {% include 'includes/pagination.html' with page=queryset current_order_value=current_order_value %}
    </div>

    <div class="pagination">
        <span class="step-links">
            {% if queryset.has_previous %}
                <a href="?page=1">&laquo; first</a>
                <a href="?page={{ queryset.previous_page_number }}">previous</a>
            {% endif %}

            <span class="current">
                Page {{ queryset.number }} of {{ queryset.paginator.num_pages }}.
            </span>

            {% if queryset.has_next %}
                <a href="?page={{ queryset.next_page_number }}">next</a>
                <a href="?page={{ queryset.paginator.num_pages }}">last &raquo;</a>
            {% endif %}
        </span>
    </div>


    <script>
        function SelectALLObjs(ele) {
            if ($(ele).prop('checked')){
                $('input[row-select]').prop('checked',true)
            }else{
                 $('input[row-select]').prop('checked',false)
            }
        }

        function ActionCheck(ele) {
            let selected_action = $("select[name='action']").val();  // 获取选择的功能
            let selected_objs = $("input[row-select]").filter(":checked");  // 获取下方所有勾选
            console.log(selected_action);
            console.log(selected_objs);
            if (!selected_action){
                alert("没有选择的执行项!");
                return false
            }
            //alert(selected_objs.length);
            if (selected_objs.length == 0 ){
                alert("没有选择数据项!");
                return false
            } else {
                // 生成一个form标签,放在form里
                let selected_ids = [];
                $.each(selected_objs, function () {
                    console.log($(this));
                    selected_ids.push($(this).val())
                });
                console.log(selected_ids);
                let input_ele = "<input type='hidden' name='selected_ids' value=" + JSON.stringify(selected_ids) + ">";
                $(ele).append(input_ele);
            }
        }
    </script>
{% endblock %}

后台处理勾选的数据和功能

修改djadmin应用的views.py,在table_detail(request, app_name, model_name)视图中增加POST逻辑处理

@login_required
def table_detail(request, app_name, model_name):
    """取出指定model里的数据返回到前端"""
    # 拿到admin_class后,通过它获取model
    admin_class = site.enable_admins[app_name][model_name]
    # print(admin_class)  # 执行djadmin.py定义的注册模型类

    # POST提交,djadmin actions
    if request.method == 'POST':
        if request.POST.get('action') and request.POST.get('selected_ids'):
            # 获取action,这个action是从djadmin中actions列表中定义的
            selected_action = request.POST.get('action')
            # 获取选中的id
            import json
            selected_ids =json.loads(request.POST.get('selected_ids'))
            print(selected_ids)  # 列表类型:['7', '6', '3']
            # 获取所有选中id的对象
            selected_objs = admin_class.model.objects.filter(id__in=selected_ids)
            # 获取djadmin中定义的actions函数
            admin_action_func = getattr(admin_class, selected_action)
            # 讲查询集执行action的功能
            admin_action_func(request, selected_objs)
            print('执行{}的功能!'.format(selected_action))
            # 防止刷新网页提交,使用跳转
            return redirect(reverse('djadmin:table_detail', args=(app_name, model_name)))

    queryset = admin_class.model.objects.all().order_by('-id')
    # print(queryset)

    # 进行过滤
    queryset, filter_conditions = get_filter_result(request, queryset)
    # 将过滤字典保存到全局注册类中
    admin_class.filter_conditions = filter_conditions

    # 搜索
    queryset, keyword = get_search_result(request, queryset, admin_class)
    admin_class.search_keyword = keyword  # 将搜索字符串保存到全局类中

    # 排序,返回排序的结果和排序的字段字典
    queryset, current_order_field = get_order_result(request, queryset, admin_class)
    # print(current_order_field)  # {'consult_content': '4'}
    # 如果有排序,保存排序的值,用于模板中在分页模块显示
    if current_order_field.values():
        current_order_value = list(current_order_field.values())[0]
    else:
        current_order_value = ''

    # 查询集结果分页
    # paginator = Paginator(queryset, 10)  # Show 10 contacts per page
    paginator = Paginator(queryset, admin_class.list_per_page)  # 获取djadmin.py中自定义的分页数量
    page = request.GET.get('page')
    try:
        queryset = paginator.get_page(page)
    except PageNotAnInteger:
        queryset = paginator.get_page(1)
    except EmptyPage:
        queryset = paginator.get_page(paginator.num_pages)

    return render(request, 'djadmin/table_detail.html', locals())

现在就可以批量执行action操作了

例如现在的数据内容如下

image.png

然后点击执行,就会修改已勾选的数据

image.png

添加默认的delete action

添加default_actions默认删除方法

直接在djadmin_base.py父类中添加默认删除方法,crm应用的djadmin.py继承后就自动拥有该方法

# djadmin/djadmin_base.py


class BaseDjAdmin(object):
    def __init__(self):
        self.actions.extend(self.default_actions)  # 创建实例进行初始化的时候,会将default_actions并到actions中

    list_display = []
    list_filter = []
    search_fields = []
    readonly_fields = []
    filter_horizontal = []
    list_per_page = 5
    actions = []
    default_actions = ['delete_selected_objs']

    def delete_selected_objs(self, request, queryset):
        import json
        from django.shortcuts import render
        print('跳转到删除函数')
        selected_ids = json.dumps([item.id for item in queryset])
        action = 'delete_selected_objs'
        return render(request, 'djadmin/table_delete_objs.html',
                      {
                          'admin_class': self,  # self就是admin_class
                          'action': action,
                          'objs': queryset,
                          'selected_ids': selected_ids
                      })

例如我们访问 http://127.0.0.1:8000/djadmin/crm/userprofile/

image.png

会出现多个删除,就需要进行有的判断

class BaseDjAdmin(object):
    def __init__(self):
        if 'delete_selected_objs' not in self.actions:  # 如果注册多个应用,不进行判断,就会创建多个删除
            self.actions.extend(self.default_actions)  # 创建实例进行初始化的时候,会将default_actions并到actions中

    # 。。。。。。
image.png

创建删除对象显示详情确认模板

在djadmin/templates/djadmin创建table_delete_objs.html,可以参考table_delete.html模板的写法

观察table_detail视图,需要选择的actionselected_ids,所以上面的类方法需要返回这些值。

另外定义一个delete_confirm,这个用于删除操作时的判断,如果得到这个值就执行删除,否则,显示删除对象显示详情模板

{% extends 'djadmin/base.html' %}

{% load djadmin_tags %}

{% block title %}
    数据表删除 - 后台管理
{% endblock %}

{% block content %}
    <h2 class="page-header">{{ model_name }}</h2>
    <h3 class="page-header alert alert-danger">你确定要删除吗?</h3>

    {% for obj in objs %}
        {% display_all_related_objs obj as all_related_obj_eles %}
        {{ all_related_obj_eles|safe }}  {# 需要加上|safe,否则会直接显示源代码 #}
    {% endfor %}

    <form method="post">
        {% csrf_token %}
        <input class="hidden" value="yes" name="delete_confirm">
        <input class="hidden" value="{{ action }}" name="action">
        <input class="hidden" value="{{ selected_ids }}" name="selected_ids">
        <input type="submit" class="btn btn-danger" value="确认删除">
    </form>
{% endblock %}

视图中判断删除返回模板

修改djadmin应用下的views.py中的table_detail视图函数,对POST逻辑机型判断,因为执行和删除都是post动作,且同时存在在该视图中

如果选择的action是delete_selected_objs则进入删除对象的父类BaseDjAdmin.delete_selected_objs

    # POST提交,djadmin actions
    if request.method == 'POST':
        if request.POST.get('action') and request.POST.get('selected_ids'):
            # 获取action,这个action是从djadmin中actions列表中定义的
            selected_action = request.POST.get('action')
            # 获取选中的id
            import json
            print(request.POST.get('selected_ids'))  # json数据["7","6","3"]
            selected_ids =json.loads(request.POST.get('selected_ids'))
            print(selected_ids)  # 列表类型:['7', '6', '3']
            # 获取所有选中id的对象
            selected_objs = admin_class.model.objects.filter(id__in=selected_ids)
            # 获取djadmin中定义的actions函数
            admin_action_func = getattr(admin_class, selected_action)

            # 默认删除功能
            if selected_action == 'delete_selected_objs':
                print('执行{}删除功能'.format(selected_action))
                # 默认情况下显示table_delete.objs.html的内容
                return admin_action_func(request, selected_objs)  # 返回admin_action_func执行方法不用再跳回来

            # 将查询集执行action的功能
            admin_action_func(request, selected_objs)
            print('执行{}的功能!'.format(selected_action))
            # 防止刷新网页提交,使用跳转
            return redirect(reverse('djadmin:table_detail', args=(app_name, model_name)))

访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/ 添加一些测试数据,选择delete_selected_objs,勾选一些数据,然后点击执行

image.png

点击执行

image.png

视图中处理删除功能逻辑

点击确认删除,会将actionselected_idsdelete_selected_objs参数传递到后端进行处理

    # POST提交,djadmin actions
    if request.method == 'POST':
        if request.POST.get('action') and request.POST.get('selected_ids'):
            # 获取action,这个action是从djadmin中actions列表中定义的
            selected_action = request.POST.get('action')
            # 获取选中的id
            import json
            selected_ids =json.loads(request.POST.get('selected_ids'))
            print(selected_ids)  # 列表类型:['7', '6', '3']
            # 获取所有选中id的对象
            selected_objs = admin_class.model.objects.filter(id__in=selected_ids)
            # 获取djadmin中定义的actions函数
            admin_action_func = getattr(admin_class, selected_action)

            # 默认删除功能
            if selected_action == 'delete_selected_objs':
                print('执行{}删除功能'.format(selected_action))
                # 提交的数据进行删除
                if request.POST.get('delete_confirm') == 'yes':
                    admin_class.model.objects.filter(id__in=selected_ids).delete()
                    return redirect(reverse('djadmin:table_detail', args=(app_name, model_name)))
                # 默认情况下显示table_delete.objs.html的内容
                return admin_action_func(request, selected_objs)  # 返回admin_action_func执行方法不用再跳回来

            # 将查询集执行action的功能
            admin_action_func(request, selected_objs)
            print('执行{}的功能!'.format(selected_action))
            # 防止刷新网页提交,使用跳转
            return redirect(reverse('djadmin:table_detail', args=(app_name, model_name)))
image.png

点击删除后,会跳回列表页面,逻辑成功。

上一篇 下一篇

猜你喜欢

热点阅读