Django组合筛选

Posted xjt2018

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 " ></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 " ></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

 

以上是关于Django组合筛选的主要内容,如果未能解决你的问题,请参考以下文章

Django实现组合搜索的方法示例

Django实现组合搜索的方法示例

Django实现组合搜索的方法示例

django中的orm中怎么对筛选结果去重

如何在 Django 中按类别筛选产品?

Django开发之路 二(django的models表查询)