zoukankan      html  css  js  c++  java
  • Django

    Django - Xadmin (三) 分页、搜索和批量操作

    分页和 ShowList 类

    因为 list_view 视图函数里面代码太多,太乱,所以将其里面的用于处理表头、处理表单数据的关键代码提取出来,作为函数包装到一个类当中,同时,将分页功能代码也封装到该类中。

    ShowList 类

    因为将代码封装成了一个类,最先重要的是初始化,这里的初始化所传参数如下:

    def __init__(self, config, data_list, request):

    config: 即每个表对应的配置类
    data_list: 数据列表
    request: 就是 Django 的响应对象

    首先,需要引入分页类。实例化分页类对象。并将其作为类的变量以方便调用。

    from Xadmin.utils.page import Pagination

    其次,更改代码,一些关键变量此时需要加上 self 或者 self.config 等。

    class ShowList(object):
        def __init__(self, config, data_list, request):
            self.config = config
            self.data_list = data_list
            self.request = request
    
            # 扩展分页类
            current_page = int(self.request.GET.get("page", 1))
            data_count = self.data_list.count()
            base_path = self.request.path
            self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=1, pager_count=3)
            self.data_page = self.data_list[self.pagination.start: self.pagination.end]
    
        def get_header(self):
            # 处理表头
            header_list = []
    
            # 为list_display的每个字段都添加相应的表头
            for field in self.config.new_display_list():
    
                # 字段为数据表自带
                if isinstance(field, str):
                    # 默认list_display
                    if field == '__str__':
                        val = self.config.model._meta.model_name.upper()
                    else:
                        field_obj = self.config.model._meta.get_field(field)
                        val = field_obj.verbose_name
                # 字段为自添加函数
                else:
                    # is_header判断是否在传表头时调用
                    val = field(self.config, is_header=True)
                header_list.append(val)
    
            return header_list
    
        def get_body(self):
            # 处理表单数据的列表
            new_data_list = []
    
            for data_obj in self.data_page:
                temp = []
                for field in self.config.new_display_list():
                    # 取数据对象相应的字段
                    if isinstance(field, str):
                        val = getattr(data_obj, field)
                        # 如果是根据该字段进入编辑页面
                        if field in self.config.list_display_links:
                            _url = self.config.get_change_url(data_obj)
                            val = mark_safe("<a href='%s'>%s</a>" % (_url, val))
                    else:
                        val = field(self.config, data_obj)
    
                    temp.append(val)
    
                new_data_list.append(temp)
    
            return new_data_list
    

    视图函数的改变

    视图函数 list_view 现在只需要构建一个 ShowList 的实例对象传到前端即可。

    # 构建ShowList列表
    showlist = ShowList(self, data_list, request)
    

    前端的改变

    之前是直接使用从后端传来的数据变量,现在从后端传来的是 ShowList 实例对象,只需将原来的数据变量改成 showlist 调用相应函数即可。

    加上了分页功能:调用 ShowList 类中 pagination 变量中的 page_html 方法。

    <table class="table table-bordered table-striped">
    	<thead>
    	<tr>
    		{% for item in showlist.get_header %}
    			<td>{{ item }}</td>
    		{% endfor %}
    
    	</tr>
    	</thead>
    	<tbody>
    	{% for new_data in showlist.get_body %}
    		<tr>
    			{% for data in new_data %}
    				<td>{{ data }}</td>
    			{% endfor %}
    
    		</tr>
    	{% endfor %}
    
    	</tbody>
    </table>
    <nav>
    	<ul class="pagination">
    		<li>{{ showlist.pagination.page_html | safe }}</li>
    	</ul>
    </nav>
    

    搜索

    前端的搜索框

    因为功能是根据后端 search_fields 列表来判断是否有搜索功能以及搜索的字段,同时通过从后端的 key_words 来保持搜索框内容:

    {% if showlist.config.search_fields %}
    	<form action="" class="pull-right">
    		<input type="text" name="q" value="{{ showlist.config.key_words }}">
    		<button>搜索</button>
    	</form>
    {% endif %}
    

    后端的处理

    在 ModelXadmin 类中增加一个变量 search_fields 来指定可以搜索的字段。默认为空,在每个表各自的配置类中可以加以指定。

    search_fields = []

    在 ModelXadmin 类中增加一个函数 get_search_condition 来获取搜索筛选的条件。

    基于 Q 函数,以 或 为连接搜索条件。

    def get_search_conditon(self, request):
    	key_words = request.GET.get("q", "")
    	self.key_words = key_words
    	from django.db.models import Q
    	search_connection = Q()
    	if key_words:
    		search_connection.connector = "or"
    		for field in self.search_fields:
    			search_connection.children.append((field + "__contains", key_words))
    
    	return search_connection
    

    最后在 list_view 中进行实际数据过滤操作。

    # 获取search的Q对象
    search_connection = self.get_search_conditon(request)
    
    # 筛选数据
    data_list = self.model.objects.filter(search_connection)
    

    批量操作

    与 admin 类似,批量操作也是选中多个数据后在下拉框中选中要做的操作。同样,定义批量操作的代码需要放在各个表的配置类中。

    前端

    因为批量操作需要对表单数据进行处理,所以要将整个表单也放到 form 中。

    <form method="post">
    	{% csrf_token %}
    	<select name="action" id="" style=" 200px;padding: 5px 8px;display: inline-block">
    		<option value="">------</option>
    		{% for action in showlist.get_action_list %}
    			<option value="{{ action.name }}">{{ action.short_description }}</option>
    		{% endfor %}
    
    	</select>
    	<button class="btn btn-info">Go</button>
    	<table>表</table>
    	<nav>分页</nav>
    </form>
    

    表的配置类

    定义批量操作函数。

    给函数加上 short_description 属性来描述和在前端显示。

    然后将批量操作函数加到配置类的 actions 列表中。

    def patch_init(self, request, queryset):
    	queryset.update(price=123)
    
    patch_init.short_description = "批量初始化"
    
    actions = [patch_init]
    

    后端

    表的配置类中,只是对批量操作函数的定义,真正运行时其实是在后端。

    从前端中获取要进行的操作和数据,并运行。重点在 action_func(request, queryset)

    def list_view(self, request):
    
    	if request.method == "POST":
    		action = request.POST.get("action")
    		selected_pk = request.POST.getlist("selected_pk")
    		action_func = getattr(self, action)
    		queryset = self.model.objects.filter(pk__in=selected_pk)
    		action_func(request, queryset)
    

    默认批量处理

    前面提到批量操作函数的定义在各个表的配置类中,可以为每个表定义各自的操作。而一些所有表都需要的批量操作,即默认批量操作,如批量删除,也是可以实现的。

    在 ModelXadmin 类中进行批量操作函数定义并加到 actions 列表中,这样,就是默认批量操作了。

    
    def patch_delete(self, request, queryset):
    	queryset.delete()
    
    patch_delete.short_description = "批量删除"
    
    def new_actions(self):
    	temp = []
    	temp.append(ModelXadmin.patch_delete)
    	temp.extend(self.actions)
    
    	return temp
    

    1542080421375

    完整代码:GitHub地址

  • 相关阅读:
    CentOS 7 rpm包部署kubernetes 1.20
    基于ipset对大量IP进行封禁(Iptables)
    RPM打包指南
    MySQL主从一致性检查
    基于Docker+Jenkins+Git的发布环境
    MySQL管理工具集MySQL Utilities | 利用frm和ibd文件恢复表数据
    MySQL日志解析工具资料汇总
    MySQL之—分库分表的技巧
    MySQL之查询重复记录、删除重复记录方法大全
    一个爬虫
  • 原文地址:https://www.cnblogs.com/banshaohuan/p/9951373.html
Copyright © 2011-2022 走看看