【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\d+)-(?P\d+)-(?P\d+).html/$', views.video),
    url('^video2-(?P\d+)-(?P\d+)-(?P\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




    
    视频-组合筛选
    


筛选

编程语言分类:

{% if kwargs.classification_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in classification_list %} {% if item.id == kwargs.classification_id %} {{ item.name }} {% else %} {{ item.name }} {% endif %} {% endfor %}

难度等级:

{% if kwargs.level_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in level_list %} {% if item.id == kwargs.level_id %} {{ item.title }} {% else %} {{ item.title }} {% endif %} {% endfor %}

上线/下线:

{% if kwargs.status == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in status_list %} {% if item.id == kwargs.status %} {{ item.name }} {% else %} {{ item.name }} {% endif %} {% endfor %}

搜索结果

{% for video in video_list %}
标题: {{ video.title }}
简介: {{ video.summary }}
图片:
视频href: {{ video.href }}

{% endfor %}

  

版本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:




    
    组合筛选2
    


筛选

视频方向:

{% if kwargs.direction_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for direction in direction_list %} {% if kwargs.direction_id == direction.id %} {{ direction.name }} {% else %} {{ direction.name }} {% endif %} {% endfor %}

语言分类:

{% if classification_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in classification_list %} {% if classification_id == item.id %} {{ item.name }} {% else %} {{ item.name }} {% endif %} {% endfor %}

难度等级:

{% if kwargs.level_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in level_list %} {% if kwargs.level_id == item.id %} {{ item.title }} {% else %} {{ item.title }} {% endif %} {% endfor %}

搜索结果

{% for video in video_list %}
标题:  {{ video.title }}
简介:  {{ video.summary }}
图片:
视频href:  {{ video.href }}

{% endfor %}
 

重要知识点总结:

1、路由中正则使用有名分组,传入的信息以字典格式保存在 视图函数的 kwargs中

url('^video-(?P\d+)-(?P\d+)-(?P\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循环遍历

编程语言分类:

{% if kwargs.classification_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for item in classification_list %} {% if item.id == kwargs.classification_id %} {{ item.name }} {% else %} {{ item.name }} {% endif %} {% endfor %}

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