Django 標簽篩選的實現(一對多、多對多)


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM