当前位置: 移动技术网 > IT编程>脚本编程>Python > Django 标签筛选的实现(一对多、多对多)

Django 标签筛选的实现(一对多、多对多)

2018年09月05日  | 移动技术网IT编程  | 我要评论

水浒传人物图片,有求必应的意思,龙珠第二部全集

django 标签筛选的实现(一对多、多对多)

实现的目标(一对多)

实现针对课程实现:课程类型、难度级别、是否隐藏三个方式的筛选

每一个视频文件有针对一个课程类型、一个难度级别、是否隐藏

设计数据库如下:

# 视频分类表格
class videotype(models.model):
    video_type = models.charfield(max_length=50)

    class meta:
        verbose_name_plural = '视频分类'

    def __str__(self):
        return self.video_type


# 视频难度表格
class videodif(models.model):
    video_dif = models.charfield(max_length=50)

    class meta:
        verbose_name_plural = '视频难度'

    def __str__(self):
        return self.video_dif


# 视频:id、视频图片、视频名称、视频简介、视频地址、视频分类、视频难度、权重、是否显示
class video(models.model):
    video_img = models.charfield(max_length=100)
    video_title = models.charfield(max_length=100)
    video_text = models.textfield()
    video_type_id = models.foreignkey('videotype', on_delete=models.cascade,)
    video_dif_id = models.foreignkey('videodif', on_delete=models.cascade,)
    video_qz = models.integerfield(default=0)
    display_choice = (
        (1, '显示'),
        (2, '隐藏'),
    )
    display = models.integerfield(verbose_name='状态', choices=display_choice, default=1)

    class meta:
        verbose_name_plural = '视频'
models

url文件:

from django.urls import re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('video/', views.video),
    # 通过正则表达式添加三个字段,从前台获取当前选择项
    re_path('video-(?p<video_type_id>(\d+))-(?p<video_dif_id>(\d+))-(?p<display>(\d+))', views.video),
url

后台程序文件:

def video(request,*args,**kwargs):
    # 给后台筛选数据库使用
    condition = {}
    
    # kwargs是从前台url获取的键值对,如果第一次访问,针对字典做一个初始化
    if not kwargs:
        kwargs ={
            'video_type_id':0,
            'video_dif_id':0,
            'display':0,
        }
        
    # 依次取出kwargs字典中传来的值
    for k, v in kwargs.items():
        # 首先将传来的值变为数字类型
        temp = int(v)
        kwargs[k] = temp
        # 如果kwargs中有值,循环将值赋予condition列表
        if temp:
            condition[k] = temp
            
    # 从数据库中获取视频类型的列表
    videotype_list = models.videotype.objects.all()
    
    # 从数据库中获取视频难度的列表
    videodif_list = models.videodif.objects.all()
    
    # 从数据库中视频列表中,获取是否显示的字段的内容,是一个元组形式的:((1, '显示'), (2, '隐藏'))
    # map后形成一个map对象:{'id':1,'name':'显示'}
    # 最后list转换为列表:[{'id': 1, 'name': '显示'}, {'id': 2, 'name': '隐藏'}]
    display_list = list(map(lambda x:{'id':x[0],'name':x[1]},models.video.display_choice))
    
    # 根据condition列表筛选数据库中的视频列表
    video_list = models.video.objects.filter(**condition)


    return render(
        request,
        'video1.html',
        {
            'videotype_list': videotype_list,
            'videodif_list': videodif_list,
            'kwargs': kwargs,
            'video_list': video_list,
            'display_list': display_list,
        }
    )
views

前台展示文件:

<!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: red;
            color: white;
        }
    </style>
</head>
<body>

    <div class="condition">
        <h1>筛选</h1>
        <div>
            {% if kwargs.video_type_id == 0%}
                <a href="/video-0-{{ kwargs.video_dif_id }}-{{ kwargs.display }}" class="active">全部</a>
            {% else %}
                <a href="/video-0-{{ kwargs.video_dif_id }}-{{ kwargs.display }}">全部</a>
            {% endif %}
            {% for i in videotype_list %}
                {% if i.id == kwargs.video_type_id %}
                    <a href="/video-{{ i.id }}-{{ kwargs.video_dif_id }}-{{ kwargs.display }}" class="active">{{ i.video_type }}</a>
                {% else %}
                    <a href="/video-{{ i.id }}-{{ kwargs.video_dif_id }}-{{ kwargs.display }}">{{ i.video_type }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div>
            {% if kwargs.video_dif_id == 0%}
                <a href="/video-{{ kwargs.video_type_id }}-0-{{ kwargs.display }}" class="active">全部</a>
            {% else %}
                <a href="/video-{{ kwargs.video_type_id }}-0-{{ kwargs.display }}">全部</a>
            {% endif %}
            {% for i in videodif_list %}
                {% if i.id == kwargs.video_dif_id %}
                    <a href="/video-{{ kwargs.video_type_id }}-{{ i.id }}-{{ kwargs.display }}" class="active">{{ i.video_dif }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.video_type_id }}-{{ i.id }}-{{ kwargs.display }}">{{ i.video_dif }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div>
            {% if kwargs.display == 0 %}
                <a class="active" href="/video-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}-0">全部</a>
            {% else %}
                <a href="/video-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}-0">全部</a>
            {% endif %}
            {% for item in display_list %}
                {% if item.id == kwargs.display %}
                    <a class="active" href="/video-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}-{{ item.id }}">{{ item.name }}</a>
                {% else %}
                    <a href="/video-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}-{{ item.id }}">{{ item.name }}</a>
                {% endif %}
            {% endfor %}
        </div>
    </div>
    <div>
        <h1>结果</h1>
        <div>
            {% for row in video_list %}
                <p>{{ row.video_title }}</p>
            {% endfor %}
        </div>
    </div>
</body>
</html>
video1.html

前台通过变化active标签,实现选中的显示,通过a标签中的数字控制后台筛选操作

 


实现的目标(多对多)

实现针对课程实现:课程方向、课程类型、难度级别三个方式的筛选

其中每个课程方向中包含有多个课程类型,选择课程方向后,筛选课程方向包含的所有课程类型

每一个视频文件有针对一个课程类型、一个难度级别

设计数据库如下,在一对多的基础上增加了一个多对多的课程方向表:

# 方向分类:id、名称(与视频—分类做多对多关系)
class videogroup(models.model):
    video_group = models.charfield(max_length=50)
    group_type = models.manytomanyfield('videotype')

    class meta:
        verbose_name_plural = '方向分类'

    def __str__(self):
        return self.video_group

# 视频分类表格
class videotype(models.model):
    video_type = models.charfield(max_length=50)

    class meta:
        verbose_name_plural = '视频分类'

    def __str__(self):
        return self.video_type


# 视频难度表格
class videodif(models.model):
    video_dif = models.charfield(max_length=50)

    class meta:
        verbose_name_plural = '视频难度'

    def __str__(self):
        return self.video_dif


# 视频:id、视频图片、视频名称、视频简介、视频地址、视频分类、视频难度、权重、是否显示
class video(models.model):
    video_img = models.charfield(max_length=100)
    video_title = models.charfield(max_length=100)
    video_text = models.textfield()
    video_type_id = models.foreignkey('videotype', on_delete=models.cascade,)
    video_dif_id = models.foreignkey('videodif', on_delete=models.cascade,)
    video_qz = models.integerfield(default=0)
    display_choice = (
        (1, '显示'),
        (2, '隐藏'),
    )
    display = models.integerfield(verbose_name='状态', choices=display_choice, default=1)

    class meta:
        verbose_name_plural = '视频'
models

url文件:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('video2/', views.video2),
    re_path('video2-(?p<video_group_id>(\d+))-(?p<video_type_id>(\d+))-(?p<video_dif_id>(\d+))', views.video2),
]
url

后台程序文件:

def video2(request, *args, **kwargs):
    condition = {}

    # 思路 -- 构造查询字典
    """
    如果:获取video_group_id=0 代表方向是全部,不会对以后的筛选造成影响
        *列出所有的type
        如果:video_type_id=0
            pass
        否则:
            condition【'video_type_id'】= video_type_id
    否则:*列出当前方向下的type
        如果:video_type_id=0
            获取当前方向下的type的所有的id【1,2,3,4】
            condition【'video_type_id__in'】= 【1,2,3,4】
        否则:
            需要查看当前的type是否在当前的方向列表中,如果在:
                condition【'video_type_id'】= video_type_id
            如果不在:
                condition【'video_type_id__in'】= 【1,2,3,4】
    """

    if not kwargs:
        kwargs = {
            'video_type_id':0,
            'video_dif_id':0,
            'video_group_id':0,
        }

    for k, v in kwargs.items():
        temp = int(v)
        kwargs[k] = temp

    # 首先从kwargs中取出相应的id
    group_id = kwargs.get('video_group_id')
    type_id = kwargs.get('video_type_id')
    dif_id = kwargs.get('video_dif_id')

    # 从数据库中取出所有的group列表,因为所有方向在页面上都要显示
    group_list = models.videogroup.objects.all()

    # 判断group值是否为0
    if group_id == 0:
        # 如果为0,则列出所有type的列表
        videotype_list = models.videotype.objects.all()
        # 如果type的列表也为0,筛选中就不用作特殊操作
        if type_id == 0:
            pass
        # 如果type的列表不为0,筛选列表中增加type的id
        else:
            condition['video_type_id'] = type_id
    # 如果group值不为0
    else:
        # 首先根据group的id筛选出分类表格中的内容,形成一个对象
        group_obj = models.videogroup.objects.filter(id=group_id).first()
        # 再根据group筛选出的对象,用多对多表格字段,筛选出所有的type的列表,等待返回给前台使用
        videotype_list = group_obj.group_type.all()
        # 获取筛选后的type的id值,得到一个queryset [(1,),(3,),(4,)]的对象
        vlist = group_obj.group_type.all().values_list('id')
        # 如果筛选后的type的值为空,也就是没有找到对应的type类型
        if not vlist:
            # 设置一个空列表
            type_ids = []
        # 如果筛选后的type值有内容
        else:
            # 将vlist进行一个zip,获得一个zip的对象,再转化为列表,得到一个【(1,3,4)】,取第一个值,得到(1,3,4)
            type_ids = list(zip(*vlist))[0]  # (1,3,4)
        
        # 判断如果前台传来的type为0的话
        if type_id == 0:
            # 后台筛选的时候,查询按照方向筛选出来的type_ids进行查询
            # __in指的是用列表方式查询多个id
            condition['video_type_id__in'] = type_ids
        # 如果前台传来的type不为0的时候,有两种情况
        else:
            # 如果前台传来的type值在后台筛选的值范围内的时候
            if type_id in type_ids:
                # 后台筛选的typeid就按照前台传来的type值筛选,也就是前台选了某个课程,如果课程方向发生改变的时候,课程类型还在选择范围内,前台也仍然是选中的状态,我们也就仍然返回选中的课程类型筛选的内容
                condition['video_type_id'] = type_id
            # 如果前台传来的type值不在后台筛选的值范围内的时候
            else:
                # 就按照后台筛选的课程方向向下的所有type类型进行筛选
                condition['video_type_id__in'] = type_ids
                kwargs['video_type_id'] = 0
    
    # 难度这边跟上面的多对多没有关联,与一对多的情况时一样
    if dif_id == 0:
        pass
    else:
        condition['video_dif_id'] = dif_id
    videodif_list = models.videodif.objects.all()
    
    # 最终将符合条件的视频筛选出来
    video_list = models.video.objects.filter(**condition)

    return render(
        request,
        'video2.html',
        {
            'group_list': group_list,
            'videotype_list': videotype_list,
            'videodif_list': videodif_list,
            'video_list': video_list,
            'kwargs': kwargs
        }
    )
views

前台展示文件:

<!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: red;
            color: white;
        }
    </style>
</head>
<body>

    <div class="condition">
        <h1>筛选</h1>
        <div>
            {% if kwargs.video_group_id == 0%}
                <a href="/video2-0-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}" class="active">全部</a>
            {% else %}
                <a href="/video2-0-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}">全部</a>
            {% endif %}

            {% for item in group_list %}
                {% if item.id == kwargs.video_group_id %}
                    <a class="active" href="/video2-{{ item.id }}-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}">{{ item.video_group }}</a>
                {% else %}
                    <a href="/video2-{{ item.id }}-{{ kwargs.video_type_id }}-{{ kwargs.video_dif_id }}">{{ item.video_group }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div>
            {% if kwargs.video_type_id == 0%}
                <a href="/video2-{{ kwargs.video_group_id }}-0-{{ kwargs.video_dif_id }}" class="active">全部</a>
            {% else %}
                <a href="/video2-{{ kwargs.video_group_id }}-0-{{ kwargs.video_dif_id }}">全部</a>
            {% endif %}

            {% for item in videotype_list %}
                {% if item.id == kwargs.video_type_id %}
                    <a class="active" href="/video2-{{ kwargs.video_group_id }}-{{ item.id }}-{{ kwargs.video_dif_id }}">{{ item.video_type }}</a>
                {% else %}
                    <a href="/video2-{{ kwargs.video_group_id }}-{{ item.id }}-{{ kwargs.video_dif_id }}">{{ item.video_type }}</a>
                {% endif %}
            {% endfor %}
        </div>
        <div>
            {% if kwargs.video_dif_id == 0%}
                <a href="/video2-{{ kwargs.video_group_id }}-{{ kwargs.video_type_id }}-0" class="active">全部</a>
            {% else %}
                <a href="/video2-{{ kwargs.video_group_id }}-{{ kwargs.video_type_id }}-0">全部</a>
            {% endif %}

            {% for item in videodif_list %}
                {% if item.id == kwargs.video_dif_id %}
                    <a class="active" href="/video2-{{ kwargs.video_group_id }}-{{ kwargs.video_type_id }}-{{ item.id }}">{{ item.video_dif }}</a>
                {% else %}
                    <a href="/video2-{{ kwargs.video_group_id }}-{{ kwargs.video_type_id }}-{{ item.id }}">{{ item.video_dif }}</a>
                {% endif %}
            {% endfor %}
        </div>
    </div>
    <div>
        <h1>结果</h1>
        <div>
            {% for item in video_list %}
                <p>{{ item.video_title }}</p>
            {% endfor %}
        </div>
    </div>
</body>
</html>
video2.html

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网