Django - Xadmin (三) 分页、搜索和批量操做
分页和 ShowList 类
由于 list_view 视图函数里面代码太多,太乱,因此将其里面的用于处理表头、处理表单数据的关键代码提取出来,做为函数包装到一个类当中,同时,将分页功能代码也封装到该类中。html
ShowList 类
由于将代码封装成了一个类,最早重要的是初始化,这里的初始化所传参数以下:前端
def __init__(self, config, data_list, request):
python
config: 即每一个表对应的配置类 data_list: 数据列表 request: 就是 Django 的响应对象git
首先,须要引入分页类。实例化分页类对象。并将其做为类的变量以方便调用。github
from Xadmin.utils.page import Pagination
django
其次,更改代码,一些关键变量此时须要加上 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 的实例对象传到前端便可。app
# 构建ShowList列表 showlist = ShowList(self, data_list, request)
前端的改变
以前是直接使用从后端传来的数据变量,如今从后端传来的是 ShowList 实例对象,只需将原来的数据变量改为 showlist 调用相应函数便可。函数
加上了分页功能:调用 ShowList 类中 pagination 变量中的 page_html 方法。post
<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="width: 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
完整代码:GitHub地址