【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

 

posted @ 2019-08-20 10:09  XJT2019  阅读(263)  评论(0编辑  收藏  举报