当前位置:首页 > PHP教程 > php高级应用 > 列表

Django 标签筛选的实现代码(一对多、多对多)

发布:smiling 来源: PHP粉丝网  添加日期:2021-10-27 15:36:46 浏览: 评论:0 

这篇文章主要介绍了Django 标签筛选的实现代码(一对多、多对多),本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下。

实现的目标(一对多)

实现针对课程实现:课程类型、难度级别、是否隐藏三个方式的筛选

每一个视频文件有针对一个课程类型、一个难度级别、是否隐藏

设计数据库如下:

  1. # 视频分类表格 
  2. class VideoType(models.Model): 
  3.  Video_Type = models.CharField(max_length=50) 
  4.  class Meta: 
  5.  verbose_name_plural = '视频分类' 
  6.  def __str__(self): 
  7.  return self.Video_Type 
  8. # 视频难度表格 
  9. class VideoDif(models.Model): 
  10.  Video_dif = models.CharField(max_length=50) 
  11.  class Meta: 
  12.  verbose_name_plural = '视频难度' 
  13.  def __str__(self): 
  14.  return self.Video_dif 
  15. # 视频:ID、视频图片、视频名称、视频简介、视频地址、视频分类、视频难度、权重、是否显示 
  16. class Video(models.Model): 
  17.  Video_img = models.CharField(max_length=100) 
  18.  Video_title = models.CharField(max_length=100) 
  19.  Video_text = models.TextField() 
  20.  Video_type_id = models.ForeignKey('VideoType', on_delete=models.CASCADE,) 
  21.  Video_dif_id = models.ForeignKey('VideoDif', on_delete=models.CASCADE,) 
  22.  Video_qz = models.IntegerField(default=0) 
  23.  display_choice = ( 
  24.  (1, '显示'), 
  25.  (2, '隐藏'), 
  26.  ) 
  27.  display = models.IntegerField(verbose_name='状态', choices=display_choice, default=1) 
  28.  class Meta: 
  29.  verbose_name_plural = '视频' 

URL文件:

  1. from django.urls import re_path 
  2. urlpatterns = [ 
  3.  path('admin/', admin.site.urls), 
  4.  path('video/', views.video), 
  5.  # 通过正则表达式添加三个字段,从前台获取当前选择项 
  6.  re_path('video-(?P<Video_type_id>(\d+))-(?P<Video_dif_id>(\d+))-(?P<display>(\d+))', views.video), 

后台程序文件:

  1. def video(request,*args,**kwargs): 
  2.  # 给后台筛选数据库使用 
  3.  condition = {} 
  4.  # kwargs是从前台URL获取的键值对,如果第一次访问,针对字典做一个初始化 
  5.  if not kwargs: 
  6.  kwargs ={ 
  7.   'Video_type_id':0, 
  8.   'Video_dif_id':0, 
  9.   'display':0, 
  10.  } 
  11.  # 依次取出kwargs字典中传来的值 
  12.  for k, v in kwargs.items(): 
  13.  # 首先将传来的值变为数字类型 
  14.  temp = int(v) 
  15.  kwargs[k] = temp 
  16.  # 如果kwargs中有值,循环将值赋予condition列表 
  17.  if temp: 
  18.   condition[k] = temp 
  19.  # 从数据库中获取视频类型的列表 
  20.  VideoType_list = models.VideoType.objects.all() 
  21.  # 从数据库中获取视频难度的列表 
  22.  VideoDif_list = models.VideoDif.objects.all() 
  23.  # 从数据库中视频列表中,获取是否显示的字段的内容,是一个元组形式的:((1, '显示'), (2, '隐藏')) 
  24.  # map后形成一个map对象:{'id':1,'name':'显示'
  25.  # 最后list转换为列表:[{'id': 1, 'name''显示'}, {'id': 2, 'name''隐藏'}] 
  26.  display_list = list(map(lambda x:{'id':x[0],'name':x[1]},models.Video.display_choice)) 
  27.  # 根据condition列表筛选数据库中的视频列表 
  28.  video_list = models.Video.objects.filter(**condition) 
  29.  return render( 
  30.  request, 
  31.  'video1.html'
  32.  { 
  33.   'VideoType_list': VideoType_list, 
  34.   'VideoDif_list': VideoDif_list, 
  35.   'kwargs': kwargs, 
  36.   'video_list': video_list, 
  37.   'display_list': display_list, 
  38.  } 
  39.  ) 

前台展示文件:

  1. <!DOCTYPE html> 
  2. <html lang="en"> 
  3. <head> 
  4.  <meta charset="UTF-8"> 
  5.  <title>Title</title> 
  6.  <style> 
  7.  .condition a{ 
  8.   display: inline-block;; 
  9.   padding: 5px 8px; 
  10.   border: 1px solid #dddddd; 
  11.  } 
  12.  .condition a.active{ 
  13.   background-color: red; 
  14.   color: white; 
  15.  } 
  16.  </style> 
  17. </head> 
  18. <body> 
  19.  <div class="condition"> 
  20.  <h1>筛选</h1> 
  21.  <div> 
  22.   {% if kwargs.Video_type_id == 0%} 
  23.   <a href="/video-0-{{ kwargs.Video_dif_id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" class="active">全部</a> 
  24.   {% else %} 
  25.   <a href="/video-0-{{ kwargs.Video_dif_id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" >全部</a> 
  26.   {% endif %} 
  27.   {% for i in VideoType_list %} 
  28.   {% if i.id == kwargs.Video_type_id %} 
  29.    <a href="/video-{{ i.id }}-{{ kwargs.Video_dif_id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" class="active">{{ i.Video_Type }}</a> 
  30.   {% else %} 
  31.    <a href="/video-{{ i.id }}-{{ kwargs.Video_dif_id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" >{{ i.Video_Type }}</a> 
  32.   {% endif %} 
  33.   {% endfor %} 
  34.  </div> 
  35.  <div> 
  36.   {% if kwargs.Video_dif_id == 0%} 
  37.   <a href="/video-{{ kwargs.Video_type_id }}-0-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" class="active">全部</a> 
  38.   {% else %} 
  39.   <a href="/video-{{ kwargs.Video_type_id }}-0-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" >全部</a> 
  40.   {% endif %} 
  41.   {% for i in VideoDif_list %} 
  42.   {% if i.id == kwargs.Video_dif_id %} 
  43.    <a href="/video-{{ kwargs.Video_type_id }}-{{ i.id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" class="active">{{ i.Video_dif }}</a> 
  44.   {% else %} 
  45.    <a href="/video-{{ kwargs.Video_type_id }}-{{ i.id }}-{{ kwargs.display }}" rel="external nofollow" rel="external nofollow" >{{ i.Video_dif }}</a> 
  46.   {% endif %} 
  47.   {% endfor %} 
  48.  </div> 
  49.  <div> 
  50.   {% if kwargs.display == 0 %} 
  51.   <a class="active" href="/video-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}-0" rel="external nofollow" rel="external nofollow" >全部</a> 
  52.   {% else %} 
  53.   <a href="/video-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}-0" rel="external nofollow" rel="external nofollow" >全部</a> 
  54.   {% endif %} 
  55.   {% for item in display_list %} 
  56.   {% if item.id == kwargs.display %} 
  57.    <a class="active" href="/video-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}-{{ item.id }}" rel="external nofollow" rel="external nofollow" >{{ item.name }}</a> 
  58.   {% else %} 
  59.    <a href="/video-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}-{{ item.id }}" rel="external nofollow" rel="external nofollow" >{{ item.name }}</a> 
  60.   {% endif %} 
  61.   {% endfor %} 
  62.  </div> 
  63.  </div> 
  64.  <div> 
  65.  <h1>结果</h1> 
  66.  <div> 
  67.   {% for row in video_list %} 
  68.   <p>{{ row.Video_title }}</p> 
  69.   {% endfor %} 
  70.  </div> 
  71.  </div> 
  72. </body> 
  73. </html> 

前台通过变化active标签,实现选中的显示,通过a标签中的数字控制后台筛选操作

实现的目标(多对多)

实现针对课程实现:课程方向、课程类型、难度级别三个方式的筛选

其中每个课程方向中包含有多个课程类型,选择课程方向后,筛选课程方向包含的所有课程类型

每一个视频文件有针对一个课程类型、一个难度级别

设计数据库如下,在一对多的基础上增加了一个多对多的课程方向表:

  1. # 方向分类:ID、名称(与视频—分类做多对多关系) 
  2. class VideoGroup(models.Model): 
  3.  Video_group = models.CharField(max_length=50) 
  4.  group_type = models.ManyToManyField('VideoType'
  5.  class Meta: 
  6.  verbose_name_plural = '方向分类' 
  7.  def __str__(self): 
  8.  return self.Video_group 
  9. # 视频分类表格 
  10. class VideoType(models.Model): 
  11.  Video_Type = models.CharField(max_length=50) 
  12.  class Meta: 
  13.  verbose_name_plural = '视频分类' 
  14.  def __str__(self): 
  15.  return self.Video_Type 
  16. # 视频难度表格 
  17. class VideoDif(models.Model): 
  18.  Video_dif = models.CharField(max_length=50) 
  19.  class Meta: 
  20.  verbose_name_plural = '视频难度' 
  21.  def __str__(self): 
  22.  return self.Video_dif 
  23. # 视频:ID、视频图片、视频名称、视频简介、视频地址、视频分类、视频难度、权重、是否显示 
  24. class Video(models.Model): 
  25.  Video_img = models.CharField(max_length=100) 
  26.  Video_title = models.CharField(max_length=100) 
  27.  Video_text = models.TextField() 
  28.  Video_type_id = models.ForeignKey('VideoType', on_delete=models.CASCADE,) 
  29.  Video_dif_id = models.ForeignKey('VideoDif', on_delete=models.CASCADE,) 
  30.  Video_qz = models.IntegerField(default=0) 
  31.  display_choice = ( 
  32.  (1, '显示'), 
  33.  (2, '隐藏'), 
  34.  ) 
  35.  display = models.IntegerField(verbose_name='状态', choices=display_choice, default=1) 
  36.  class Meta: 
  37.  verbose_name_plural = '视频' 

URL文件:

  1. urlpatterns = [ 
  2.  path('admin/', admin.site.urls), 
  3.  path('video2/', views.video2), 
  4.  re_path('video2-(?P<Video_group_id>(\d+))-(?P<Video_type_id>(\d+))-(?P<Video_dif_id>(\d+))', views.video2), 

后台程序文件:

  1. def video2(request, *args, **kwargs): 
  2.  condition = {} 
  3.  # 思路 -- 构造查询字典 
  4.  ""
  5.  如果:获取Video_group_id=0 代表方向是全部,不会对以后的筛选造成影响 
  6.  *列出所有的type 
  7.  如果:Video_type_id=0 
  8.   pass 
  9.  否则: 
  10.   condition【'Video_type_id'】= Video_type_id 
  11.  否则:*列出当前方向下的type 
  12.  如果:Video_type_id=0 
  13.   获取当前方向下的type的所有的id【1,2,3,4】 
  14.   condition【'Video_type_id__in'】= 【1,2,3,4】 
  15.  否则: 
  16.   需要查看当前的type是否在当前的方向列表中,如果在: 
  17.   condition【'Video_type_id'】= Video_type_id 
  18.   如果不在: 
  19.   condition【'Video_type_id__in'】= 【1,2,3,4】 
  20.  ""
  21.  if not kwargs: 
  22.  kwargs = { 
  23.   'Video_type_id':0, 
  24.   'Video_dif_id':0, 
  25.   'Video_group_id':0, 
  26.  } 
  27.  for k, v in kwargs.items(): 
  28.  temp = int(v) 
  29.  kwargs[k] = temp 
  30.  # 首先从kwargs中取出相应的id 
  31.  group_id = kwargs.get('Video_group_id'
  32.  type_id = kwargs.get('Video_type_id'
  33.  dif_id = kwargs.get('Video_dif_id'
  34.  # 从数据库中取出所有的group列表,因为所有方向在页面上都要显示 
  35.  group_list = models.VideoGroup.objects.all() 
  36.  # 判断group值是否为0 
  37.  if group_id == 0: 
  38.  # 如果为0,则列出所有type的列表 
  39.  VideoType_list = models.VideoType.objects.all() 
  40.  # 如果type的列表也为0,筛选中就不用作特殊操作 
  41.  if type_id == 0: 
  42.   pass 
  43.  # 如果type的列表不为0,筛选列表中增加type的id 
  44.  else
  45.   condition['Video_type_id'] = type_id 
  46.  # 如果group值不为0 
  47.  else
  48.  # 首先根据group的id筛选出分类表格中的内容,形成一个对象 
  49.  group_obj = models.VideoGroup.objects.filter(id=group_id).first() 
  50.  # 再根据group筛选出的对象,用多对多表格字段,筛选出所有的type的列表,等待返回给前台使用 
  51.  VideoType_list = group_obj.group_type.all() 
  52.  # 获取筛选后的type的id值,得到一个QuerySet [(1,),(3,),(4,)]的对象 
  53.  vlist = group_obj.group_type.all().values_list('id'
  54.  # 如果筛选后的type的值为空,也就是没有找到对应的type类型 
  55.  if not vlist: 
  56.   # 设置一个空列表 
  57.   type_ids = [] 
  58.  # 如果筛选后的type值有内容 
  59.  else
  60.   # 将vlist进行一个zip,获得一个zip的对象,再转化为列表,得到一个【(1,3,4)】,取第一个值,得到(1,3,4) 
  61.   type_ids = list(zip(*vlist))[0] # (1,3,4) 
  62.  # 判断如果前台传来的type为0的话 
  63.  if type_id == 0: 
  64.   # 后台筛选的时候,查询按照方向筛选出来的type_ids进行查询 
  65.   # __in指的是用列表方式查询多个id 
  66.   condition['Video_type_id__in'] = type_ids 
  67.  # 如果前台传来的type不为0的时候,有两种情况 
  68.  else
  69.   # 如果前台传来的type值在后台筛选的值范围内的时候 
  70.   if type_id in type_ids: 
  71.   # 后台筛选的typeid就按照前台传来的type值筛选,也就是前台选了某个课程,如果课程方向发生改变的时候,课程类型还在选择范围内,前台也仍然是选中的状态,我们也就仍然返回选中的课程类型筛选的内容 
  72.   condition['Video_type_id'] = type_id 
  73.   # 如果前台传来的type值不在后台筛选的值范围内的时候 
  74.   else
  75.   # 就按照后台筛选的课程方向向下的所有type类型进行筛选 
  76.   condition['Video_type_id__in'] = type_ids 
  77.   kwargs['Video_type_id'] = 0 
  78.  # 难度这边跟上面的多对多没有关联,与一对多的情况时一样 
  79.  if dif_id == 0: 
  80.  pass 
  81.  else
  82.  condition['Video_dif_id'] = dif_id 
  83.  VideoDif_list = models.VideoDif.objects.all() 
  84.  # 最终将符合条件的视频筛选出来 
  85.  video_list = models.Video.objects.filter(**condition) 
  86.  return render( 
  87.  request, 
  88.  'video2.html'
  89.  { 
  90.   'group_list': group_list, 
  91.   'VideoType_list': VideoType_list, 
  92.   'VideoDif_list': VideoDif_list, 
  93.   'video_list': video_list, 
  94.   'kwargs': kwargs 
  95.  } 
  96.  ) 

前台展示文件:

  1. <!DOCTYPE html> 
  2. <html lang="en"> 
  3. <head> 
  4.  <meta charset="UTF-8"> 
  5.  <title>Title</title> 
  6.  <style> 
  7.  .condition a{ 
  8.   display: inline-block;; 
  9.   padding: 5px 8px; 
  10.   border: 1px solid #dddddd; 
  11.  } 
  12.  .condition a.active{ 
  13.   background-color: red; 
  14.   color: white; 
  15.  } 
  16.  </style> 
  17. </head> 
  18. <body> 
  19.  <div class="condition"> 
  20.  <h1>筛选</h1> 
  21.  <div> 
  22.   {% if kwargs.Video_group_id == 0%} 
  23.   <a href="/video2-0-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" class="active">全部</a> 
  24.   {% else %} 
  25.   <a href="/video2-0-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >全部</a> 
  26.   {% endif %} 
  27.   {% for item in group_list %} 
  28.   {% if item.id == kwargs.Video_group_id %} 
  29.    <a class="active" href="/video2-{{ item.id }}-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_group }}</a> 
  30.   {% else %} 
  31.    <a href="/video2-{{ item.id }}-{{ kwargs.Video_type_id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_group }}</a> 
  32.   {% endif %} 
  33.   {% endfor %} 
  34.  </div> 
  35.  <div> 
  36.   {% if kwargs.Video_type_id == 0%} 
  37.   <a href="/video2-{{ kwargs.Video_group_id }}-0-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" class="active">全部</a> 
  38.   {% else %} 
  39.   <a href="/video2-{{ kwargs.Video_group_id }}-0-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >全部</a> 
  40.   {% endif %} 
  41.   {% for item in VideoType_list %} 
  42.   {% if item.id == kwargs.Video_type_id %} 
  43.    <a class="active" href="/video2-{{ kwargs.Video_group_id }}-{{ item.id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_Type }}</a> 
  44.   {% else %} 
  45.    <a href="/video2-{{ kwargs.Video_group_id }}-{{ item.id }}-{{ kwargs.Video_dif_id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_Type }}</a> 
  46.   {% endif %} 
  47.   {% endfor %} 
  48.  </div> 
  49.  <div> 
  50.   {% if kwargs.Video_dif_id == 0%} 
  51.   <a href="/video2-{{ kwargs.Video_group_id }}-{{ kwargs.Video_type_id }}-0" rel="external nofollow" rel="external nofollow" class="active">全部</a> 
  52.   {% else %} 
  53.   <a href="/video2-{{ kwargs.Video_group_id }}-{{ kwargs.Video_type_id }}-0" rel="external nofollow" rel="external nofollow" >全部</a> 
  54.   {% endif %} 
  55.   {% for item in VideoDif_list %} 
  56.   {% if item.id == kwargs.Video_dif_id %} 
  57.    <a class="active" href="/video2-{{ kwargs.Video_group_id }}-{{ kwargs.Video_type_id }}-{{ item.id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_dif }}</a> 
  58.   {% else %} 
  59.    <a href="/video2-{{ kwargs.Video_group_id }}-{{ kwargs.Video_type_id }}-{{ item.id }}" rel="external nofollow" rel="external nofollow" >{{ item.Video_dif }}</a> 
  60.   {% endif %} 
  61.   {% endfor %} 
  62.  </div> 
  63.  </div> 
  64.  <div> 
  65.  <h1>结果</h1> 
  66.  <div> 
  67.   {% for item in video_list %} 
  68.   <p>{{ item.Video_title }}</p> 
  69.   {% endfor %} 
  70.  </div> 
  71.  </div> 
  72. </body> 
  73. </html>

Tags: Django标签筛选

分享到: