【Django】组合筛选
组合筛选
数据库表设计:
from django.db import models class Direction(models.Model): ''' 视频方向:全栈、前端、后端、测试、运维、自动化 ''' name = models.CharField(max_length=32,verbose_name="方向名称") m = models.ManyToManyField("Classification") # 别名 class Meta: verbose_name_plural = "方向分类" def __str__(self): return self.name class Classification(models.Model): ''' 语言分类:Python、Java、HTML、css、selenium、NodeJs、OpenStack ''' name = models.CharField(max_length=32,verbose_name="视频分类") #别名 class Meta: 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(choices=status_choice,default=1,verbose_name="状态") level = models.ForeignKey("Level",on_delete=models.CASCADE) classification = models.ForeignKey("Classification",null=True,on_delete=models.CASCADE,verbose_name="语言分类") weight = models.IntegerField(verbose_name="权重(按照从大到小排列)") title = models.CharField(max_length=32,verbose_name="标题") summary = models.CharField(max_length=512, verbose_name="简介") img = models.ImageField(verbose_name="图片",upload_to="static/images") href = models.URLField(verbose_name="视频地址",max_length=64) class Meta: db_table = "Video" verbose_name_plural = "视频" def __str__(self): return self.title
路由分发:
from django.contrib import admin from django.conf.urls import url from app01 import views urlpatterns = [ url('admin/', admin.site.urls), url('^video-(?P<classification_id>\d+)-(?P<level_id>\d+)-(?P<status>\d+).html/$', views.video), url('^video2-(?P<direction_id>\d+)-(?P<classification_id>\d+)-(?P<level_id>\d+).html/$', views.video2), ]
版本1、一对多筛选
效果:
视图函数views.py
from django.shortcuts import render from app01.models import Classification,Direction,Level,Video def video(request,*args,**kwargs): condition = { # "classification_id":0 # "level_id":0, # "status":0 } print("kwargs--->",kwargs) #url的 video-1-1 的分类classification_id=1 level_id=1 保存到kwargs # kwargs - --> {'classification_id': '1', 'level_id': '1','status':'1'} #键值对 都是字符串格式 for k,v in kwargs.items(): temp = int(v) kwargs[k] = temp if temp: #当temp==0 时,condition=={} 即filter() 过滤条件为空,匹配所有 condition[k] = temp classification_list = Classification.objects.all() level_list = Level.objects.all() status_list = Video.status_choice # status_choice = ( # (1, "上线"), (2, "下线") # ) # 在模板语言中 循环体内调用方式为 item.0 item.1 ,这样子很不直观 # 可以将status_choice 改变为 [{'id':1,'name':'上线'},{'id':2,'name':'下线'}] status_list = list(map(lambda x:{"id":x[0],"name":x[1]},status_list)) video_list = Video.objects.filter(**condition) return render( request, "video.html", { "classification_list":classification_list, "level_list":level_list, "kwargs":kwargs, "video_list":video_list, "status_list":status_list, } )
视图函数views.py
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>视频-组合筛选</title> <style> a.btn{ font-size: 16px; border: 1px solid orange; font-weight: 500; padding: 10px; text-decoration: none; border-radius: 5px; } .row{ font-size: 20px; margin-top: 30px; } .active{ background-color: orangered; color: white; font-weight: 700; } .resultShow{ border: 1px dotted darkblue; } .resultShow div{ margin: 20px; } </style> </head> <body> <div class="contents"> <div class="selectorBox"> <h1>筛选</h1> <div class="classes row"> <p>编程语言分类:</p> {% if kwargs.classification_id == 0 %} <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active btn">全部</a> {% else %} <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="btn">全部</a> {% endif %} {% for item in classification_list %} {% if item.id == kwargs.classification_id %} <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active btn">{{ item.name }}</a> {% else %} <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="btn">{{ item.name }}</a> {% endif %} {% endfor %} </div> <div class="level row"> <p>难度等级:</p> {% if kwargs.level_id == 0 %} <a href="/video-{{ kwargs.classification_id }}-0-{{ kwargs.status }}.html" class="active btn">全部</a> {% else %} <a href="/video-{{ kwargs.classification_id }}-0-{{ kwargs.status }}.html" class="btn">全部</a> {% endif %} {% for item in level_list %} {% if item.id == kwargs.level_id %} <a href="/video-{{ kwargs.classification_id }}-{{ item.id }}-{{ kwargs.status }}.html" class="active btn">{{ item.title }}</a> {% else %} <a href="/video-{{ kwargs.classification_id }}-{{ item.id }}-{{ kwargs.status }}.html" class="btn">{{ item.title }}</a> {% endif %} {% endfor %} </div> <div class="status row"> <p>上线/下线:</p> {% if kwargs.status == 0 %} <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-0.html" class="active btn">全部</a> {% else %} <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-0.html" class="btn">全部</a> {% endif %} {% for item in status_list %} {% if item.id == kwargs.status %} <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-{{ item.id }}.html" class="active btn">{{ item.name }}</a> {% else %} <a href="/video-{{ kwargs.classification_id }}-{{ kwargs.level_id }}-{{ item.id }}.html" class="btn">{{ item.name }}</a> {% endif %} {% endfor %} </div> </div> <div class="resultBox"> <h1>搜索结果</h1> <div class="resultShow"> {% for video in video_list %} <div><span>标题:</span> <span style="font-size: 26px;font-weight: 700;color: orangered">{{ video.title }}</span></div> <div><span>简介:</span> <span>{{ video.summary }}</span></div> <div><span>图片:</span><img src="/static/images/{{ video.img }}" alt=""></div> <div><span>视频href:</span> <a href="{{ video.href }}">{{ video.href }}</a></div> <hr> {% endfor %} </div> </div> </div> </body> </html>
版本2、多对多筛选
效果:
视图函数views.py
from django.shortcuts import render from app01.models import Classification,Direction,Level,Video def video2(request,*args,**kwargs): print(kwargs) direction_list = Direction.objects.all() for k,v in kwargs.items(): kwargs[k] = int(v) direction_id = kwargs["direction_id"] classification_id = kwargs["classification_id"] condition = {} classification_id_list = [] if direction_id: direction_obj = Direction.objects.filter(id=direction_id).first() vlist = direction_obj.m.all().values_list("id") if vlist: 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: ###方向id=1时 分类id=[1,2,3] 但是你url传入的分类id=4 不在[1,2,3]中。则classification_id == direction_id所对应的则classification_id condition["classification_id__in"] = classification_id_list classification_id = 0 cls_condition = {"id__in": list(classification_id_list)} classification_list = Classification.objects.filter(**cls_condition) else: classification_list = Classification.objects.all() if kwargs["level_id"]: condition["level_id"] = kwargs["level_id"] level_list = Level.objects.all() video_list = Video.objects.filter(**condition) print(condition,video_list) return render(request,"video2.html",{ "direction_list": direction_list, "classification_list": classification_list, "level_list": level_list, "classification_id":classification_id, "kwargs": kwargs, "video_list": video_list, })
模板HTML:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>组合筛选2</title> <style> a.btn{ font-size: 16px; border: 1px solid orange; font-weight: 500; padding: 10px; text-decoration: none; border-radius: 5px; } .row{ font-size: 20px; margin-top: 30px; } .active{ background-color: orangered; color: white; font-weight: 700; } .resultShow{ border: 1px dotted darkblue; } .resultShow div{ margin: 20px; } </style> </head> <body> <div class="contents"> <div class="selectorBox"> <h1>筛选</h1> <div class="directions row"> <p>视频方向:</p> {% if kwargs.direction_id == 0 %} <a href="/video2-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html" class="btn active">全部</a> {% else %} <a href="/video2-0-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html" class="btn">全部</a> {% endif %} {% for direction in direction_list %} {% if kwargs.direction_id == direction.id %} <a href="/video2-{{ direction.id }}-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html" class="btn active">{{ direction.name }}</a> {% else %} <a href="/video2-{{ direction.id }}-{{ kwargs.classification_id }}-{{ kwargs.level_id }}.html" class="btn">{{ direction.name }}</a> {% endif %} {% endfor %} </div> <div class="classifications row"> <p>语言分类:</p> {% if classification_id == 0 %} <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html" class="btn active">全部</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-0-{{ kwargs.level_id }}.html" class="btn">全部</a> {% endif %} {% for item in classification_list %} {% if classification_id == item.id %} <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html" class="btn active">{{ item.name }}</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level_id }}.html" class="btn">{{ item.name }}</a> {% endif %} {% endfor %} </div> <div class="levels row"> <p>难度等级:</p> {% if kwargs.level_id == 0 %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html" class="btn active">全部</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html" class="btn">全部</a> {% endif %} {% for item in level_list %} {% if kwargs.level_id == item.id %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html" class="btn active">{{ item.title }}</a> {% else %} <a href="/video2-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.id }}.html" class="btn">{{ item.title }}</a> {% endif %} {% endfor %} </div> </div> <div class="resultBox"> <h1>搜索结果</h1> <div class="resultShow"> {% for video in video_list %} <div><span>标题:</span> <span style="font-size: 26px;font-weight: 700;color: orangered">{{ video.title }}</span></div> <div><span>简介:</span> <span>{{ video.summary }}</span></div> <div><span>图片:</span><img src="/static/images/{{ video.img }}" alt=""></div> <div><span>视频href:</span> <a href="{{ video.href }}">{{ video.href }}</a></div> <hr> {% endfor %} </div> </div> </div> </body> </html>
重要知识点总结:
1、路由中正则使用有名分组,传入的信息以字典格式保存在 视图函数的 kwargs中
url('^video-(?P<classification_id>\d+)-(?P<level_id>\d+)-(?P<status>\d+).html/$', views.video), -------------------------------------------------------------------------views.py print("kwargs--->",kwargs) #url的 video-1-1 的分类classification_id=1 level_id=1 保存到kwargs # kwargs - --> {'classification_id': '1', 'level_id': '1','status':'2'} #键值对 都是字符串格式
2、map() 函数的用法:
yuanzu = ((1,"在线"),(2,"下线")) status_list = list(map(lambda x:{"id":x[0],"name":x[1]},yuanzu)) print(status_list) #[{'id': 1, 'name': '在线'}, {'id': 2, 'name': '下线'}] s_li = ["beijing",3,"zhejiang",7] def multi(s): if type(s)==int: return s**2 elif type(s) == str: return s.upper() else: return s print(list(map(lambda x:multi(x),s_li))) #['BEIJING', 9, 'ZHEJIANG', 49]
3、zip() 函数用法:
# zip() 方法 v1 = [1,2,3] v2=[44,55,66] print(list(zip(v1,v2))) #二合一 #[(1, 44), (2, 55), (3, 66)] print(list(zip(*[[11,22,33],[1,5,9]]))) #一分二 #[(11, 1), (22, 5), (33, 9)] print(list(zip(*[(11,22,33),(44,55,66,77)]))) # [(11, 44), (22, 55), (33, 66)]
4、模板语言 if 判断是否选中,以及for循环遍历
<div class="classes row"> <p>编程语言分类:</p> {% if kwargs.classification_id == 0 %} <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active btn">全部</a> {% else %} <a href="/video-0-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="btn">全部</a> {% endif %} {% for item in classification_list %} {% if item.id == kwargs.classification_id %} <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="active btn">{{ item.name }}</a> {% else %} <a href="/video-{{ item.id }}-{{ kwargs.level_id }}-{{ kwargs.status }}.html" class="btn">{{ item.name }}</a> {% endif %} {% endfor %} </div>
5、多对多筛选条件判断
def video2(request,*args,**kwargs): print(kwargs) direction_list = Direction.objects.all() #将字典 value值变为整数 for k,v in kwargs.items(): kwargs[k] = int(v) direction_id = kwargs["direction_id"] classification_id = kwargs["classification_id"] condition = {} classification_id_list = [] #如果direction_id !=0 if direction_id: direction_obj = Direction.objects.filter(id=direction_id).first() vlist = direction_obj.m.all().values_list("id") #如果方向id 下对应有分类 if vlist: classification_id_list = list(zip(*vlist))[0] #分类id=0 if classification_id == 0: condition["classification_id__in"] = classification_id_list else: # 分类id 在方向id对应的分类列表中 if classification_id in classification_id_list: condition["classification_id"] = classification_id else: ###方向id=1时 分类id=[1,2,3] 但是你url传入的分类id=4 不在[1,2,3]中。则classification_id == direction_id所对应的则classification_id condition["classification_id__in"] = classification_id_list classification_id = 0 cls_condition = {"id__in": list(classification_id_list)} classification_list = Classification.objects.filter(**cls_condition) else: classification_list = Classification.objects.all() if kwargs["level_id"]: #如果等级id不为0 则写入条件字典 condition["level_id"] = kwargs["level_id"] level_list = Level.objects.all() video_list = Video.objects.filter(**condition) print(condition,video_list) return render(request,"video2.html",{ "direction_list": direction_list, "classification_list": classification_list, "level_list": level_list, "classification_id":classification_id, "kwargs": kwargs, "video_list": video_list, })
参考:
https://www.cnblogs.com/ccorz/p/5985205.html
https://www.jianshu.com/p/8402823e8f1b