一、本节目标
上一节实现了分页功能的开发,这一节开发排序功能
二、Django实现分析
Django的admin排序功能是通过点击字段名称,来实现排序,点一次升序,再点一次降序,并且可以多列排序,根据字段的索引顺序来判断是哪个字段要排序
同时搜索栏会根据正序倒序进行变换:
正序:
倒序:
通过超链接来向后端发送排序请求
三、功能开发
这里只开发单行排序。也根据字段的索引顺序来判断字段。
1、第一步,添加一<a>链接
这样就有超链接了,如图所示:
点击,地址栏里就会显示参数:
2、需要把对应的索引值传给查询参数,然后传给后台进行查询:
也就是说,点击排序列,把索引值传给o,然后通过request就能获取到排序的索引了,因此,还得在前端这里操作:
这里需要用到Django模板的forloop这个功能,就是通过forloop返回对应列的索引值,这样就跟admin实现一样了。
这个功能具体查看这里:https://www.cnblogs.com/realizetomoney/p/13887676.html
在tag里写一个函数,获取forloop的值,并返回给前端
在前端引入tag:
3、在views中写视图函数,将排序列传给后端进行排序,并返回:
4、在table_obj_list中对querysets进行排序
5、查看页面,发现已经可以排序了,点击某些列不会动,是因为默认排序是升序排序,它本来就是升序的,所以没动,可以打印一下,从后台看就知道了:
6、但是,有个问题是,admin点击一次排序,再点击一次反向排序,反向排序是前边加个负号。目前我们的实现是,点击一次是默认状态下的升序排序,再次点击也没有进行反向排序,因此需要修改。
开发设计思路:
如果当前是升序排序,点击一次是降序排序,
如果是降序排序,点击一次是升序排序。
因此,需要记住上一次排序的状态,可以设计一个字典来存储:例如{o:1},
这个字典写在哪里?经过试验,发现在返回forloop时,所有的forloop都返回,所以没法通过索引判断是哪个字段排序,因此不能写在tag里,只能写在views视图函数里,通过request获取排序的字段。
7、视图函数修改,添加返回排序的列的状态:
8、table_obj_list需要将当前排序列返回给前端:
9、tag是返回排序的索引,因此tag需要根据记录的排序列状态,将返回的forloop值,根据情况判断,是否加上“-”号
10、此时查看,发现可以排序:
11、美化
查看admin,可以发现admin排序列右边有三角符号,我们也做一个。
首先,从bootstrap,Boorstrap组件:https://v3.bootcss.com/components/,将下图中的代码拷贝过来备用,下边根据排序情况动态生成此图标
将对应的font文件放到static里:
因为是动态生成的,因此还是需要用到tag,在tag里编写如下函数,动态生成这个图标:
在正向排序的时候,箭头朝上,降序排序的时候,箭头朝下,因此需要先判断,然后根据判断动态生成:
前端在column后添加这个箭头:
页面显示结果如下:
四、功能完善
1、目前已经可以排序了,但是没有与过滤结合,这里解决一下与过滤结合的问题。
参考admin,是通过url这么一拼接就实现了,我们也这么个思路实现
admin的实现方法是url拼接,我们也做一个url拼接。
如果把排序的url放到过滤的url里,这个不会做,也不太合理,因为过滤的同时是没有点击排序的,没有排序的效果,当你过滤完毕点击排序,此时又没有过滤的效果,因此把过滤条件拼接一下放在排序的url里。
过滤的所有条件都在filter_conditions里存着呢,因此从filter_conditions里取值拼接即可。
然后将此tag放到排序的url里:
此时排序就可以与过滤结合了:
2、过滤和分页组合:
总体思路还是url拼接,将过滤条件的url拼接后放到分页的url里
然后在前端页面修改:
然后在页面上查看,可以过滤的同时分页:
3、过滤,排序,分页组合
目前,排序与过滤组合可以了,过滤与分页组合也可以了,但是三个组合在一起还不可以,因此需要继续开发。
思路还是拼接url,跟过滤与分页方法一致。
具体操作细节就是,如何从视图函数中返回的sorted_column中,querysets,sorted_column = get_orderby_result(request,querysets,admin_class),取出排序的索引:
sorted_column是由如下视图函数生成的current_ordered_column,是一个字典,问题就集中在了如何从字典中取出value:
def get_orderby_result(request,querysets,admin_class):
#添加一个字典,用来存储当前排序列的状态
current_ordered_column = {}
orderby_index = request.GET.get('o')
if orderby_index:
# 通过索引找到要排序的字段,因为索引有可能是负数,要用绝对值,否则负值的时候取到了其它字段了
orderby_key = admin_class.list_display[abs(int(orderby_index))]
current_ordered_column[orderby_key] = orderby_index
if orderby_index.startswith('-'):
orderby_key = '-'+orderby_key
#print(querysets.order_by(orderby_key))
return querysets.order_by(orderby_key),current_ordered_column
else:
return querysets,current_ordered_column
通过实验可以看出,用dict.values比较好,因此:
此时三个功能组合可用: