组合搜索
组合搜索 |
一、概述
组合搜索指的是根据特定标签内容,返回符合的数据。
二、功能实现
首先我们要实现下面所示的效果图:
1.设计规划
(1)数据库表划分:
- 方向表,(自动化,测试,闹完,打杂)
- 分类表,(Python,Linux,GO,JavaScrip,OpenStack,Node.js、C)
- 等级表,(初级,中级,高级,骨灰级)
- 录像表,(录像1,录像2。。。)
(2)表间关系
- 方向表与分类表之间为多对多关系
- 等级表与录像表之间为一对多关系
(3)表内详细设计:
方向表:
class Direction(models.Model): """ 方向:自动化,测试,运维,前端 """ name = models.CharField(verbose_name='名称', max_length=32) classification = models.ManyToManyField('Classification') class Meta: db_table = 'Direction' verbose_name_plural = '方向(视频方向)' def __str__(self): return self.name
分类表:
class Classification(models.Model): """ 分类:Python Linux JavaScript OpenStack Node.js """ name = models.CharField(verbose_name='名称', max_length=32) class Meta: db_table = 'Classification' verbose_name_plural = '分类(视频分类)' def __str__(self): return self.name
等级表:
class Level(models.Model): title = models.CharField(max_length=32) class Meta: verbose_name_plural = '难度级别' def __str__(self): return self.title
视频表:
class Video(models.Model): status_choice = ( (1, '下线'), (2, '上线'), ) status = models.IntegerField(verbose_name='状态', choices=status_choice, default=1) level = models.ForeignKey(Level) classification = models.ForeignKey('Classification', null=True, blank=True) weight = models.IntegerField(verbose_name='权重(按从大到小排列)', default=0) title = models.CharField(verbose_name='标题', max_length=32) summary = models.CharField(verbose_name='简介', max_length=32) img = models.CharField(verbose_name='图片',max_length=32) href = models.CharField(verbose_name='视频地址', max_length=256) create_date = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'Video' verbose_name_plural = '视频' def __str__(self): return self.title
2.具体效果
通过对比其他同类型的搜索示例发现,他们大多数都通过URL地址来向后台传递类别 id 查询数据库,然后返回数据给前端页面。
可以发现:方向对应第一个数字,分类对应第二个数字,等级对应第三个数字。
方向的标签代码为:
当点击分类或等级时,其自身对应的id数字会发生改变,而另外两个数字id不产生变化。
设计步骤:
(1)我们先设计出通过输入网页URL地址的方式,动态改变页面标签代码中的值。
设计URL选择器,正则表达式:
url(r'^video2-(?P<direction_id>(\d+))-(?P<classification_id>(\d+))-(?P<level_id>(\d+)).html$', views.video2,name='video2')
其中direction_id为方向id,classfication_id为分类id,level_id为等级id。
(2)输入正确的url传递给views.py下video2()函数处理。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def video2(request,*args,**kwargs): condition = {} for k, v in kwargs.items(): temp = int(v) kwargs[k] = temp print(kwargs) # (?P<direction_id>(\d+))-(?P<classification_id>(\d+))-(?P<level_id>(\d+)) # 构造查询字典 direction_id = kwargs.get('direction_id') classification_id = kwargs.get('classification_id') level_id = kwargs.get('level_id') direction_list = models.Direction.objects.all() if direction_id == 0: class_list = models.Classification.objects.all() if classification_id == 0: pass else: condition['classification_id'] = classification_id else: direction_obj = models.Direction.objects.filter(id=direction_id).first() class_list = direction_obj.classification.all() vlist = direction_obj.classification.all().values_list('id') if not vlist: classification_id_list = [] else: classification_id_list = list(zip(*vlist))[0] if classification_id == 0: condition['classification_id__in'] = classification_id_list else: if classification_id in classification_id_list: condition['classification_id'] = classification_id else: #################指定方向:[1,2,3] 分类:5 kwargs['classification_id'] = 0 condition['classification_id__in'] = classification_id_list if level_id == 0: pass else: condition['level_id'] = level_id level_list = models.Level.objects.all() video_list = models.Video.objects.filter(**condition) return render( request, 'video2.html', { 'direction_list':direction_list, 'class_list':class_list, 'level_list':level_list, 'video_list':video_list, 'kwargs':kwargs, } )
从上述代码可以看出我们设计当id=0时为获得全部数据,因为数据库中id字段是从1开始递增的。判断语句所表达意思如下:
""" 如果:direction_id = 0 *列出所有的分类 如果 classification_id = 0: pass else: condition['classification_id'] = classification_id 否则:direction_id != 0 *列表当前方向下的所有分类 如果 classification_id = 0: 获取当前方向下的所有分类 [1,2,3,4] condition['classification_id__in'] = [1,2,3,4] else: classification_id != 0 获取当前方向下的所有分类 [1,2,3,4] classification_id 是否在 [1,2,3,4] : condition['classification_id'] = classification_id else: condition['classification_id__in'] = [1,2,3,4] """
(3)前端接收到当前url地址后,通过模版语言,动态的构造a标签的href属性,即可表现为当改变url时,标签href也同时发生改变。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .condition a{ display: inline-block; padding: 5px 8px; border: 1px solid #dddddd; } .condition a.active{ background-color: coral; color: white; } </style> </head> <body> <div class="condition"> <h1>筛选</h1> <div> {% if kwargs.direction_id == 0 %} <a href="{% url "video2" direction_id=0 classification_id=kwargs.classification_id level_id=kwargs.level_id %}" class="active">全部</a> {% else %} <a href="{% url "video2" direction_id=0 classification_id=kwargs.classification_id level_id=kwargs.level_id %}">全部</a> {% endif %} {% for item in direction_list %} {% if item.id == kwargs.direction_id %} <a href="{% url "video2" direction_id=item.id classification_id=kwargs.classification_id level_id=kwargs.level_id %}" class="active">{{ item.name }}</a> {% else %} <a href="{% url "video2" direction_id=item.id classification_id=kwargs.classification_id level_id=kwargs.level_id %}">{{ item.name }}</a> {% endif %} {% endfor %} </div> <div> {% if kwargs.classification_id == 0 %} <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html" class="active">全部</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html">全部</a> {% endif %} {% for item in class_list %} {% if item.id == kwargs.classification_id %} <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html" class="active">{{ item.name }}</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html" >{{ item.name }}</a> {% endif %} {% endfor %} </div> <div> {% if kwargs.level_id == 0 %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html" class="active">全部</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html">全部</a> {% endif %} {% for item in level_list %} {% if item.id == kwargs.level_id %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html" class="active">{{ item.title }}</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html" >{{ item.title }}</a> {% endif %} {% endfor %} </div> </div> <div> <h1>结果</h1> {% for row in video_list %} <div>{{ row.title }}</div> {% endfor %} </div> </body> </html>