执行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增加数据选项
- 获取执行的功能,如果没有选择,则提示;
- 获取勾选的数据项;如果没有勾选,则提示;
- 如果勾选了,将勾选的id放在一个序列中,转换成json格式;
- 最后使用一个隐藏的input标签,添加到form内;
- 提交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">« 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 »</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_base.py中添加一个
delete_selected_objs
方法,该方法会渲染table_delete.html显示删除的哪些对象 - 添加一个
default_actions = ['delete_selected_objs']
,不能直接加到actions里面,因为子类会覆盖父类的actions - 利用
__init__
方法,把default_actions
里面的值添加到actions
里面
# 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
视图,需要选择的action
、selected_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视图中处理删除功能逻辑
点击确认删除,会将action
、selected_ids
、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
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
点击删除后,会跳回列表页面,逻辑成功。
网友评论