• Python入门自学进阶-Web框架——25、DjangoAdmin项目应用-分页与过滤


    对于数据很多,就需要将数据进行分页显示,同时还要提供过滤功能。

    当配置文件中配置了过滤条件,那就要在显示表信息的时候,显示过滤条件选择项,选择后进行过滤,然后下面显示过滤后的数据,如果数据过多,则分页显示。

    配置文件在ClassAdmin中配置,如Customer的配置文件:

    1. class CustomerAdmin(BaseAdmin):
    2. list_display = ['qq','name','phone','source','referral_from','consult_course','tags','status']
    3. list_per_page = 3
    4. list_filter = ['source','status','qq']

    配置了过滤按source和status,每页显示3条。

    一、显示页码的实现

    实现如下样式页码:

     实现方式是在后端形成页码的html代码,然后嵌入。前端部分代码

    1. <div class="p-1 mb-2 text-info">
    2. <nav aria-label="Page navigation">
    3. <ul class="pagination">
    4. {{ page_tag | safe }}
    5. {# <li class="page-item"><a class="page-link" href="#">Previousa>li>#}
    6. {# <li class="page-item active"><a class="page-link" href="/mytestapp/plcrm/customer/?p=1">1a>li>#}
    7. {# <li class="page-item"><a class="page-link" href="/mytestapp/plcrm/customer/?p=2">2a>li>#}
    8. {# <li class="page-item"><a class="page-link" href="#">3a>li>#}
    9. {# <li class="page-item"><a class="page-link" href="#">Nexta>li>#}
    10. ul>
    11. nav>
    12. div>

    主要是page_tag,在视图函数中形成此页码代码:

    1. def display_table_objs(req,app_name,table_name):
    2. url_path = req.path
    3. current_page = int(req.GET.get('p',1))
    4. admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    5. per_page = admin_class.list_per_page
    6. total_count = admin_class.model.objects.count()
    7. obj_page = PageHelper(total_count,current_page,url_path,page_rec_count=per_page)
    8. page_tag = obj_page.pager_tag_str()
    9. return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class,"model_class_name":admin_class.model.__name__,'page_tag':page_tag,'obj_page':obj_page,'total_count':total_count})

    这里借助了以前写的页码形成的组件PageHelper类:

    1. class PageHelper:
    2. # 产生一个分页字符串,形式如下:
    3. # 上一页 1 2 3 4 5 6 7 8 9 10 11 下一页
    4. def __init__(self,total_rec_count,current_page,base_url,page_rec_count=10):
    5. # total_rec_count:查询到的记录的总条数
    6. # current_page:当前页码,即要显示哪一页,点击相应页码时的页码值
    7. # base_url:查询使用的url
    8. # page_rec_count:每页显示的记录条数,默认10条
    9. self.total_rec_count = total_rec_count
    10. self.current_page = current_page
    11. self.page_rec_count = page_rec_count
    12. self.base_url = base_url
    13. @property
    14. def page_rec_start(self):
    15. # 返回当前显示页的记录的开始值
    16. return (self.current_page - 1)*self.page_rec_count
    17. @property
    18. def page_rec_end(self):
    19. # 返回当前显示页的记录的结束值
    20. return self.current_page * self.page_rec_count
    21. def total_page_count(self):
    22. # 计算总共有多少页
    23. v, a = divmod(self.total_rec_count, self.page_rec_count)
    24. if a != 0:
    25. v += 1
    26. return v
    27. def pager_tag_str(self):
    28. # 返回一个页码字符串
    29. v = self.total_page_count()
    30. page_list = []
    31. # 判断输入的页码是否在合理范围内,因为是get请求,可以在地址栏中随意输入
    32. # 如果请求的页码小于1,就设为1,如果请求的页码大于总页码,就设为最后一个页码
    33. if self.current_page < 1:
    34. self.current_page = 1
    35. elif self.current_page > v:
    36. self.current_page = v
    37. # 页码只显示最多N条,这里假设11条,加上前后的上一页和下一页
    38. # 例如显示第10页,则页码显示10的前后5条,即从5到15页显示在页面上
    39. if v <= 11:
    40. # 页数小于11页,所有页码都显示出来就可以了
    41. page_range_start = 1
    42. page_range_end = v + 1
    43. else:
    44. if self.current_page < 6:
    45. # 总的页数大于11,并且当前选择的页码小于6,显示的是从1开始的11个页码
    46. page_range_start = 1
    47. page_range_end = 12
    48. else:
    49. # 总的页数大于11,并且当前选择的页码大于等于6,显示的页码是当前页的前后5个加上当前页共11个页码
    50. # 此时,显示的开始页码就是当前页-5,显示的最后页码就是当前页+5,range范围需要在加1.
    51. page_range_start = self.current_page - 5
    52. page_range_end = self.current_page + 5 + 1
    53. if page_range_end > v:
    54. page_range_end = v + 1
    55. page_range_start = v - 10
    56. if self.current_page == 1:
    57. # 当前页码为1时,上一页不能在进行计算
    58. page_list.append('
    59. 上一页
    60. ')
  • else:
  • page_list.append('
  • 上一页
  • ' % (self.base_url,self.current_page - 1,))
  • for i in range(page_range_start, page_range_end):
  • if i == self.current_page:
  • # 对于当前选择的页码,需要突出显示
  • page_list.append('
  • %s
  • ' % (self.base_url,i, i))
  • else:
  • page_list.append('
  • %s
  • ' % (self.base_url,i, i))
  • if self.current_page == v:
  • # 当前页码为最后一页时,下一页不能在进行计算
  • page_list.append('
  • 下一页
  • ')
  • else:
  • page_list.append('
  • 下一页
  • ' % (self.base_url,self.current_page + 1,))
  • page_tag = "".join(page_list)
  • return page_tag
  • 二、实现过滤功能,就是增加查询项,将上面显示页面的测试,换成下列选择框,然后提交,后端做条件查询

    先在前端加上静态下拉框,

    1. <form>
    2. <div class="row" style="padding-left: 10px;">
    3. <div class="col-sm">
    4. <span>qq:span>
    5. <select name="qq">
    6. <option value="">---------option>
    7. <option value="33333">333333option>
    8. select>
    9. div>
    10. <div class="col-sm">
    11. <span>status:span>
    12. <select name="status">
    13. <option value="">---------option>
    14. <option value="1">1option>
    15. select>
    16. div>
    17. <div class="col-sm">
    18. <span>source:span>
    19. <select name="source">
    20. <option value="">---------option>
    21. <option value="2">222222option>
    22. select>
    23. div>
    24. <div class="col-sm">
    25. <input type="submit" value="SUBMIT"/>
    26. div>
    27. div>
    28. form>

    样子希望如下:

     要动态生成红框中的部分,要解决的问题,一是根据Admin_class中的配置项filter_list动态生成下拉框,二是解决页码问题。有过滤项后,显示的数据是过滤后的数据,页码也应该是过滤后的记录的页码,而上一步生成页码,默认是全部数据进行分页。

    在前端页面增加如下代码:

     视图函数中生成一个filter_tag变量,这个变量保存生成的过滤栏的html代码,看一下视图函数:

    1. def display_table_objs(req,app_name,table_name):
    2. url_path = req.path # 请求的路径
    3. current_page = int(req.GET.get('p',1)) # 当前页,如果没有,即第一次查询,页面为1
    4. admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    5. filter_f_a = {} # 保存传递过来的过虑项键值对
    6. for filter_f in admin_class.list_filter:
    7. f_temp = req.GET.get(filter_f)
    8. if f_temp:
    9. filter_f_a[filter_f] = f_temp
    10. filter_url = ""
    11. if filter_f_a.__len__() != 0:
    12. for k,v in filter_f_a.items():
    13. filter_url = filter_url +"&"+ k + "=" + str(v)
    14. # 按照过滤键值对,生成页码显示时的过滤字符串,如&source=1&tags=2,在有过滤的情况下,页码必须带上过滤条件,否则就是全部数据
    15. per_page = admin_class.list_per_page # 每页多少条数据
    16. total_count = admin_class.model.objects.filter(**filter_f_a).count() # 查询数据的总条数
    17. obj_page = PageHelper(total_count,current_page,url_path,page_rec_count=per_page,filter_url=filter_url)
    18. page_tag = obj_page.pager_tag_str()
    19. filter_tag = myutils.built_filter_tag(admin_class,filter_f_a)
    20. return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class,"model_class_name":admin_class.model.__name__,'page_tag':page_tag,'obj_page':obj_page,'total_count':total_count,'filter_tag':filter_tag,'filter_f_a':filter_f_a})

    url_path是请求的路径,在形成页码的a标签时,是href的值的一部分,href的格式如下:
    href=/mytestapp/plcrm/customer/?consult_course=1&tags=2&p=1

    url_path就是问号?前的部分,filter_url就是过滤部分,p也是过滤条件,但不是输入框输入的,是页码值,通过这个几个部分,共同组成页码对应的访问地址。

    PageHelper类进行修改,增加参数filter_url,在形成页码时,将过滤条件加上。

    filter_tag由built_filter_tag形成:

    1. # 将分页做成一个通用的工具类
    2. class PageHelper:
    3. # 产生一个分页字符串,形式如下:
    4. # 上一页 1 2 3 4 5 6 7 8 9 10 11 下一页
    5. def __init__(self,total_rec_count,current_page,base_url,page_rec_count=10,filter_url=""):
    6. # total_rec_count:查询到的记录的总条数
    7. # current_page:当前页码,即要显示哪一页,点击相应页码时的页码值
    8. # base_url:查询使用的url
    9. # page_rec_count:每页显示的记录条数,默认10条
    10. self.total_rec_count = total_rec_count
    11. self.current_page = current_page
    12. self.page_rec_count = page_rec_count
    13. self.base_url = base_url
    14. self.filter_url = filter_url
    15. @property
    16. def page_rec_start(self):
    17. # 返回当前显示页的记录的开始值
    18. return (self.current_page - 1)*self.page_rec_count
    19. @property
    20. def page_rec_end(self):
    21. # 返回当前显示页的记录的结束值
    22. return self.current_page * self.page_rec_count
    23. def total_page_count(self):
    24. # 计算总共有多少页
    25. v, a = divmod(self.total_rec_count, self.page_rec_count)
    26. if a != 0:
    27. v += 1
    28. return v
    29. def pager_tag_str(self):
    30. # 返回一个页码字符串
    31. v = self.total_page_count()
    32. page_list = []
    33. # 判断输入的页码是否在合理范围内,因为是get请求,可以在地址栏中随意输入
    34. # 如果请求的页码小于1,就设为1,如果请求的页码大于总页码,就设为最后一个页码
    35. if self.current_page < 1:
    36. self.current_page = 1
    37. elif self.current_page > v:
    38. self.current_page = v
    39. # 页码只显示最多N条,这里假设11条,加上前后的上一页和下一页
    40. # 例如显示第10页,则页码显示10的前后5条,即从5到15页显示在页面上
    41. if v <= 11:
    42. # 页数小于11页,所有页码都显示出来就可以了
    43. page_range_start = 1
    44. page_range_end = v + 1
    45. else:
    46. if self.current_page < 6:
    47. # 总的页数大于11,并且当前选择的页码小于6,显示的是从1开始的11个页码
    48. page_range_start = 1
    49. page_range_end = 12
    50. else:
    51. # 总的页数大于11,并且当前选择的页码大于等于6,显示的页码是当前页的前后5个加上当前页共11个页码
    52. # 此时,显示的开始页码就是当前页-5,显示的最后页码就是当前页+5,range范围需要在加1.
    53. page_range_start = self.current_page - 5
    54. page_range_end = self.current_page + 5 + 1
    55. if page_range_end > v:
    56. page_range_end = v + 1
    57. page_range_start = v - 10
    58. if self.current_page == 1:
    59. # 当前页码为1时,上一页不能在进行计算
    60. page_list.append('
    61. 上一页
    62. ')
    63. else:
    64. page_list.append('
    65. 上一页
    66. ' % (self.base_url,self.filter_url,self.current_page - 1,))
    67. for i in range(page_range_start, page_range_end):
    68. if i == self.current_page:
    69. # 对于当前选择的页码,需要突出显示
    70. page_list.append('
    71. %s
    72. ' % (self.base_url,self.filter_url,i, i))
    73. else:
    74. page_list.append('
    75. %s
    76. ' % (self.base_url,self.filter_url,i, i))
    77. if self.current_page == v:
    78. # 当前页码为最后一页时,下一页不能在进行计算
    79. page_list.append('
    80. 下一页
    81. ')
    82. else:
    83. page_list.append('
    84. 下一页
    85. ' % (self.base_url,self.filter_url,self.current_page + 1,))
    86. page_tag = "".join(page_list)
    87. return page_tag
    1. from django.utils.timezone import datetime,timedelta
    2. def built_filter_tag(admin_class,filter_f):
    3. filter_tag = ""
    4. if admin_class.list_filter.__len__()>0:
    5. filter_tag = filter_tag + ''''
    6. '''
    7. for filter_item in admin_class.list_filter:
    8. filter_tag = filter_tag + '''
    9. %s
    10. %s
    11. ''' %(filter_item,filter_tag_value(admin_class,filter_item,filter_f))
    12. filter_tag = filter_tag + '''
    13. '''
    14. return filter_tag
    15. def filter_tag_value(admin_class,filter_item,filter_f):
    16. models_class = admin_class.model
    17. option_tag =""
    18. field_obj = models_class._meta.get_field(filter_item)
    19. # 如果是外键,使用select标签
    20. if type(field_obj).__name__ in ['ForeignKey','OneToOneFiled','ManyToManyField']:
    21. option_tag =option_tag + ''
    22. # 如果含有choices,使用select标签
    23. elif field_obj.choices:
    24. option_tag = option_tag + ''
    25. # 如果是日期型,构造如下的结构,使用select标签
    26. elif type(field_obj).__name__ in ['DateTimeField','DateField']:
    27. date_els = []
    28. today_ele = datetime.now().date()
    29. date_els.append(['今天', datetime.now().date()])
    30. date_els.append(["昨天", today_ele - timedelta(days=1)])
    31. date_els.append(["近7天", today_ele - timedelta(days=7)])
    32. date_els.append(["本月", today_ele.replace(day=1)])
    33. date_els.append(["近30天", today_ele - timedelta(days=30)])
    34. date_els.append(["近90天", today_ele - timedelta(days=90)])
    35. date_els.append(["近180天", today_ele - timedelta(days=180)])
    36. date_els.append(["本年", today_ele.replace(month=1, day=1)])
    37. date_els.append(["近一年", today_ele - timedelta(days=365)])
    38. option_tag = option_tag + ''
    39. # 以上类型都不是,就使用输入框input text
    40. else:
    41. if (filter_item in filter_f):
    42. option_tag = option_tag + '' % (filter_item,filter_f[filter_item])
    43. else:
    44. option_tag = option_tag + '' % (filter_item)
    45. return option_tag

    关于过滤标签的形成,关键的几点:
    1)根据字段类型,形成不同的标签,如下拉标签、输入框等;
    2)在进行页码切换时,需要保持过虑项的原值;

    三、数据排序,点击数据列表的字段,实现按相关字段进行排序,排序是在过滤以后的结果上进行的。

    首先是对表头字段的修改,改为a标签:

    1. class="text-danger" style="background-color: #9fcdff;">
    2. {# {% for column in admin_class.list_display %}#}
    3. {# #}
    4. {# {{ column }} #}
    5. {# {% endfor %}#}
    6. {{ header_order_tag | safe }}

    这里直接在视图函数中组装表头标签,动态生成,在三种状态间转换:默认无排序,点击第一次,按升序排序,字段后边加上上箭头“↑”,点击第二次,按降序排序,字段后边加上下箭头“↓”,第三次点击,又变为默认无排序。

    1. def display_table_objs(req,app_name,table_name):
    2. url_path = req.path
    3. current_order_mark = req.GET.get('order_mark','0')
    4. current_page = int(req.GET.get('p',1))
    5. admin_class = mytestapp_admin.enable_admins[app_name][table_name]
    6. filter_f_a = {} # 保存传递过来的顾虑项键值对
    7. for filter_f in admin_class.list_filter:
    8. f_temp = req.GET.get(filter_f)
    9. if f_temp:
    10. filter_f_a[filter_f] = f_temp
    11. print('filter_f_a:',filter_f_a)
    12. filter_url = ""
    13. # 过滤条件形成请求地址的参数串
    14. if filter_f_a.__len__() != 0:
    15. for k,v in filter_f_a.items():
    16. filter_url = filter_url + k + "=" + str(v) +"&"
    17. print(filter_url)
    18. order_url = ""
    19. if current_order_mark == '0':
    20. order_url = filter_url
    21. else:
    22. order_url = order_url + "order_mark=" + current_order_mark +"&"
    23. per_page = admin_class.list_per_page
    24. total_count = admin_class.model.objects.filter(**filter_f_a).count()
    25. print('url_path:',url_path)
    26. obj_page = PageHelper(total_count,current_page,url_path,page_rec_count=per_page,filter_url=filter_url,order_url=order_url)
    27. page_tag = obj_page.pager_tag_str()
    28. filter_tag = myutils.built_filter_tag(admin_class,filter_f_a,url_path)
    29. header_order_tag = myutils.order_tag(admin_class,url_path,filter_url,current_order_mark)
    30. return render(req,"mytestapp/table_objs.html",{"admin_class":admin_class,"model_class_name":admin_class.model.__name__,
    31. 'page_tag':page_tag,'obj_page':obj_page,'total_count':total_count,
    32. 'filter_tag':filter_tag,'filter_f_a':filter_f_a,'header_order_tag':header_order_tag,'order_mark':current_order_mark})

    增加current_order_mark,记录当前排序标志,如果是没有排序,前端不传递order_mark参数,默认取值‘0’,否则,就是传递过来的值,主要是“字段名”或“-字段名”,减号+字段名,在使用model类的order_by()时,字段名前加减号,就是降序排序。

    order_url,是形成排序参数字段的,即形成order_mark=id&这种形式,然后拼接到a标签的请求地址中传递到后台,后台根据这个值进行排序。

    注意三个url串:url_path、filter_url、order_url的区别,url_path是请求的地址,filter_url是请求的过滤参数,order_url是请求的排序参数。

    字段头的html字符串是header_order_tag,其形成函数:myutils.order_tag(admin_class,url_path,filter_url,current_order_mark)

    1. def order_tag(admin_class,url_path,filter_url,order_mark):
    2. header_order_tag = ""
    3. if order_mark == 0:
    4. for column in admin_class.list_display:
    5. header_order_tag = header_order_tag + ' %s'%(url_path,filter_url,column,column)
    6. elif not order_mark.startswith('-'):
    7. for column in admin_class.list_display:
    8. if order_mark == column:
    9. header_order_tag = header_order_tag + ' %s'%(url_path,filter_url,'-'+column,column)
    10. else:
    11. header_order_tag = header_order_tag + ' %s' % (url_path, filter_url, column, column)
    12. else:
    13. for column in admin_class.list_display:
    14. if order_mark[1:] == column:
    15. header_order_tag = header_order_tag + ' %s'%(url_path,filter_url,column)
    16. else:
    17. header_order_tag = header_order_tag + ' %s' % (url_path, filter_url, column, column)
    18. return header_order_tag

    这里要注意的是:order_mark='0',表明当前不排序,但是其a标签的href,即请求地址,是下一次点击的地址,即升序排序的地址,order_mark值是字段名,依此类推。

    同时,分页标签也要进行修改,页码的地址要将排序参数加上:
    obj_page = PageHelper(total_count,current_page,url_path,page_rec_count=per_page,filter_url=filter_url,order_url=order_url)

    1. # 将分页做成一个通用的工具类
    2. class PageHelper:
    3. # 产生一个分页字符串,形式如下:
    4. # 上一页 1 2 3 4 5 6 7 8 9 10 11 下一页
    5. def __init__(self,total_rec_count,current_page,base_url,page_rec_count=10,filter_url="",order_url=""):
    6. # total_rec_count:查询到的记录的总条数
    7. # current_page:当前页码,即要显示哪一页,点击相应页码时的页码值
    8. # base_url:查询使用的url
    9. # page_rec_count:每页显示的记录条数,默认10条
    10. self.total_rec_count = total_rec_count
    11. self.current_page = current_page
    12. self.page_rec_count = page_rec_count
    13. self.base_url = base_url
    14. self.filter_url = filter_url
    15. self.order_url = order_url # 增加排序标志字段
    16. # ..... 中间不变的省略
    17. def pager_tag_str(self):
    18. # ..... 中间不变的省略
    19. if self.current_page == 1:
    20. # 当前页码为1时,上一页不能在进行计算
    21. page_list.append('
    22. 上一页
    23. ')
    24. else:
    25. page_list.append('
    26. 上一页
    27. ' % (self.base_url,self.filter_url,self.order_url,self.current_page - 1,))
    28. for i in range(page_range_start, page_range_end):
    29. if i == self.current_page:
    30. # 对于当前选择的页码,需要突出显示
    31. page_list.append('
    32. %s
    33. ' % (self.base_url,self.filter_url,self.order_url,i, i))
    34. else:
    35. page_list.append('
    36. %s
    37. ' % (self.base_url,self.filter_url,self.order_url,i, i))
    38. if self.current_page == v:
    39. # 当前页码为最后一页时,下一页不能在进行计算
    40. page_list.append('
    41. 下一页
    42. ')
    43. else:
    44. page_list.append('
    45. 下一页
    46. ' % (self.base_url,self.filter_url,self.order_url,self.current_page + 1,))
    47. page_tag = "".join(page_list)
    48. return page_tag

    主要注意a标签的href变化。

    最后就是数据的形成:

    1. @register.simple_tag
    2. def get_query_sets_1(admin_class,obj_page,filter_f,order_mark):
    3. print('order_mark:',order_mark)
    4. if order_mark == '0':
    5. return_sets = admin_class.model.objects.filter(**filter_f)[obj_page.page_rec_start:obj_page.page_rec_end]
    6. else:
    7. return_sets = admin_class.model.objects.filter(**filter_f).order_by(order_mark)[obj_page.page_rec_start:obj_page.page_rec_end]
    8. print('数据清单标签...>>>',return_sets)
    9. return return_sets

    总结上述功能实现,关键点是相关参数在前端和后端的传递,前端相关html代码的自动生成,尤其是下一次请求的请求参数的拼接形成。

    四、查询功能实现,类似过滤功能。这里的过滤是按照AdminClass类中配置的list_search,进行查询,list_search可以配置多个字段,也就是在这多个字段中查询,只要包含相应数据,就要查询出来,相当于或关系查询。此时就需要使用Q查询。

    前端查询标签的生成,与过滤标签做在一个form中:

    1. def built_filter_tag(admin_class,filter_f,url_path,search_mark):
    2. filter_tag = ""
    3. if (admin_class.list_filter.__len__()+admin_class.list_search.__len__())>0:
    4. filter_tag = filter_tag + ''''
    5. '''%(url_path)
    6. if admin_class.list_filter.__len__()>0:
    7. for filter_item in admin_class.list_filter:
    8. filter_tag = filter_tag + '''
    9. %s
    10. %s
    11. ''' %(filter_item,filter_tag_value(admin_class,filter_item,filter_f))
    12. if admin_class.list_search.__len__()>0:
    13. filter_tag = filter_tag + '

      ' # 如果有查询,关闭上面的div,另起一个div,即另起一行
    14. if search_mark.__len__()==0:
    15. filter_tag = filter_tag + '''
    16. 查询
    17. '''
    18. else:
    19. filter_tag = filter_tag + '''
    20. 查询
    21. '''%search_mark
    22. filter_tag = filter_tag + '''
    23. '''
    24. print(filter_tag)
    25. return filter_tag

    要注意的是对于分页时,要将查询输入的值带入其他页中。

    后台查询数据时,要使用Q查询,因为是在几个字段中查找包含查询值的记录,所以是或关系,同时要与过滤条件与关系查询,即先过虑,在过滤的基础上在或查询。

    1. @register.simple_tag
    2. def get_query_sets_1(admin_class,obj_page,filter_f,order_mark,search_mark):
    3. print('order_mark:',order_mark,'search_mark',search_mark)
    4. if order_mark == '0':
    5. if search_mark.__len__() == 0:
    6. return_sets = admin_class.model.objects.filter(**filter_f)[obj_page.page_rec_start:obj_page.page_rec_end]
    7. else:
    8. q_and = Q()
    9. q_or = Q()
    10. q_or.connector = 'OR'
    11. for column in admin_class.list_search:
    12. q_or.children.append(("%s__contains" % column, search_mark))
    13. q_and.connector = "AND"
    14. # q_and.children.append(**filter_f)
    15. # q_and.children.append(q_or)
    16. return_sets = admin_class.model.objects.filter(**filter_f).filter(q_or)[obj_page.page_rec_start:obj_page.page_rec_end]
    17. else:
    18. if search_mark.__len__() == 0:
    19. return_sets = admin_class.model.objects.filter(**filter_f).order_by(order_mark)[obj_page.page_rec_start:obj_page.page_rec_end]
    20. else:
    21. q_and = Q()
    22. q_or = Q()
    23. q_or.connector = 'OR'
    24. for column in admin_class.list_search:
    25. q_or.children.append(("%s__contains" % column, search_mark))
    26. q_and.connector = "AND"
    27. # q_and.children.append(**filter_f)
    28. # q_and.children.append(q_or)
    29. return_sets = admin_class.model.objects.filter(**filter_f).filter(q_or).order_by(order_mark)[obj_page.page_rec_start:obj_page.page_rec_end]
    30. print('数据清单标签...>>>',return_sets)
    31. return return_sets
    32. # return admin_class.model.objects.values_list(*admin_class.list_display)

    通过过滤、查询、排序、分页四项功能的实现,开发这类系统的关键点就是前后端参数的传递、数据的查询、前端将数据与相关标签的组装,形成最终的显示HTML代码,传递到前端显示。

    最终的页面:

     

  • 相关阅读:
    网络、网络协议模型、UDP编程——计算机网络——day01
    公司建设网站的好处及优势
    RobotFramework之如何使用数据驱动(十二)
    什么是Ribbon,怎么实现负载均衡?
    1.5-18:鸡尾酒疗法
    如何理解深度学习的训练过程
    前端开发面经1
    C++设计模式-享元(Flyweight)
    [NISACTF 2022]下
    windows server 2019 、win11安装docker desktop
  • 原文地址:https://blog.csdn.net/kaoa000/article/details/127564685