前言
许多网站页面顶部有诸多的搜索条件供于点击联合查询,今天我们就来自定制在Django中实现分级查询
效果如图:
Model表创建
根据上图,视频方向与视频分类是多对多的关系,视频分类与视频信息是一对多的关系,难度级别是单一的查询条件(与之前俩者并无关系)
Models.py如下:
class Direction(models.Model): """ 视频方向 """ weight = models.IntegerField(verbose_name='权重(从大到小)', default=0) name = models.CharField(verbose_name='名称', max_length=32) classification = models.ManyToManyField('Classification') class Meta: db_table = 'Direction' verbose_name_plural = '方向(视频方向)' def __str__(self): return self.name class Classification(models.Model): """ 视频分类表 """ weigth = models.IntegerField(verbose_name='权重(从大到小)', default=0) name = models.CharField(verbose_name='名称', max_length=32) class Meta: db_table = 'Classification' verbose_name_plural = '分类(视频分类)' def __str__(self): return self.name class Video(models.Model): """ 视频信息表 """ status_choice = ( (0, '下线'), (1, '上线'), ) level_choice = ( (1, '初级'), (2, '中级'), (3, '高级'), ) status = models.IntegerField(verbose_name='状态', choices=status_choice, default=1) level = models.IntegerField(verbose_name='级别', choices=level_choice, default=1) classification = models.ForeignKey('Classification', null=True, blank=True) weight = models.IntegerField(verbose_name='权重(从大到小)', default=0) title = models.CharField(verbose_name='标题', max_length=32) summary = models.CharField(verbose_name='简介', max_length=32) img = models.ImageField(verbose_name='图片', upload_to='./static/images/Video/') href = models.CharField(verbose_name='视频地址', max_length=255) create_date = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'Video' verbose_name_plural = '视频' def __str__(self): return self.title
Url映射
Url映射获取搜索条件如下:
在url路由配置中,可以有命名的传参得到 视频方向ID 视频分类ID 视频难度ID 三个条件
url.py
from django.conf.urls import url from django.contrib import admin from web_manage import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'videos-(?P<direction_id>d+)-(?P<classification_id>d+)-(?P<level>d+).html',views.videos) ]
Views函数
Views函数(video)处理思路如下:
A、在视图函数中,获取到 方向、分类、难度三个值,并创建搜索条件的字典
B、HTML页面显示
- 在HTML页面,视频方向的选项一直存在;
- 视频分类在视频方向的选择项为全部时则全部展现,当视频方向(全部除外)为指定项时,则显示指定视频方向下的视频分类;
- 难度依旧显示所有选项。
C、搜索条件构建
a、如果未指定方向(全部对应的ID为0)
b、如果指定视频方向(全部除外)
-
- 应获取指定视频方向下的视频分类
- 视频方向下没有视频分类的情况,列举为
-
如果指定了视频方向,视频分类简单分为俩种情况
- 视频分类选项为全部(全部对应ID为0)
- 视频分类被指定(特殊情况:如果视频分类被指定更换视频方向)
1、视频分类存在于更替的视频方向的情况下,则分类不变
2、视频分类不存在于更替的视频方向的情况下,则分类选中全部
c、难度级别筛选
d、查询
view.py
from django.shortcuts import render,HttpResponse from django.http import JsonResponse from app01 import models import json def video(request,*args,**kwargs): #构造搜索条件字典 condition = {} for k, v in kwargs.items(): temp = int(v) kwargs[k] = temp # (?P<direction_id>(d+))-(?P<classification_id>(d+))-(?P<level_id>(d+)) # 构造查询字典 direction_id = kwargs.get('direction_id') classification_id = kwargs.get('classification_id') level_id = kwargs.get('level_id') direction_list = models.Direction.objects.all() #如果未指定视频方向 if direction_id == 0: #视频分类获取全部 class_list = models.Classification.objects.all() #如果未指定视频分类,默认查询条件应根据难度,无分类查询 if classification_id == 0: pass else: #指定视频分类,搜索字典构建的分类ID为url取到的分类ID condition['classification_id'] = classification_id #如果指定视频方向 else: #获取当前指定视频方向 direction_obj = models.Direction.objects.filter(id=direction_id).first() #获取视频方向对应的所有视频分类 class_list = direction_obj.classification.all() #获取视频方向对应的所有视频分类的ID vlist = direction_obj.classification.all().values_list('id') #如果视频方向没有分类 if not vlist: classification_id_list = [] #方向有分类 else: #zip用法 classification_id_list = list(zip(*vlist))[0] # 如果url分类ID为0 搜索条件 分类则为 指定方向下的所有分类 if classification_id == 0: # 搜索字典 特殊 赋值 了不起的下划线之 __in condition['classification_id__in'] = classification_id_list #指定方向下指定了分类 else: # 如果 分类ID 存在于 指定方向的 所有分类ID内 if classification_id in classification_id_list: condition['classification_id'] = classification_id # 如果更替指定方向,分类不变 不存在于 该方向的所有分类内 else: #################指定方向:[1,2,3] 分类:5 #即默认指定所有 kwargs['classification_id'] = 0 condition['classification_id__in'] = classification_id_list #视频级别 #如果未指定难度级别 if level_id == 0: pass #难度级别被指定 else: condition['level_id'] = level_id level_list = models.Level.objects.all() video_list = models.Video.objects.filter(**condition) return render( request, 'video.html', { 'direction_list':direction_list, 'class_list':class_list, 'level_list':level_list, 'video_list':video_list, 'kwargs':kwargs, } ) """ 如果:direction_id 0 *列出所有的分类 如果 classification_id = 0: pass else: condition['classification_id'] = classification_id 否则:direction_id != 0 *列表当前方向下的所有分类 如果 classification_id = 0: 获取当前方向下的所有分类 [1,2,3,4] condition['classification_id__in'] = [1,2,3,4] else: classification_id != 0 获取当前方向下的所有分类 [1,2,3,4] classification_id 是否在 [1,2,3,4] : condition['classification_id'] = classification_id else: condition['classification_id__in'] = [1,2,3,4] """ # models.Video.objects.filter() # return render(request,'video.html')
Html生成
<div class="search"> <div class="filter" auto-id="search_filter"> <!-- 方向类选取 --> <dl class="clearfix"> <dt>方向:</dt> <dd class="" id="purpose_status"> {% if kwargs.direction_id == 0 %} <a class="selected" href='/videos-0-{{ kwargs.classification_id }}-{{ kwargs.level }}.html'>全部</a> {% else %} <a href='/videos-0-{{ kwargs.classification_id }}-{{ kwargs.level }}.html'>全部</a> {% endif %} {% for item in direction %} {% if item.id == kwargs.direction_id %} <a class="selected" href="/videos-{{ item.id }}-{{ kwargs.classification_id }}-{{ kwargs.level }}.html">{{ item.name }}</a> {% else %} <a href="/videos-{{ item.id }}-{{ kwargs.classification_id }}-{{ kwargs.level }}.html">{{ item.name }}</a> {% endif %} {% endfor %} </dd> </dl> <dl class="clearfix"> <dt>分类:</dt> <dd id="material_status"> {% if kwargs.classification_id == 0 %} <a class="selected" href="/videos-{{ kwargs.direction_id }}-0-{{ kwargs.level }}.html">全部</a> {% else %} <a href="/videos-{{ kwargs.direction_id }}-0-{{ kwargs.level }}.html">全部</a> {% endif %} {% for item in classification %} {% if item.id == kwargs.classification_id %} <a class="selected" href="/videos-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level }}.html">{{ item.name }}</a> {% else %} <a href="/videos-{{ kwargs.direction_id }}-{{ item.id }}-{{ kwargs.level }}.html">{{ item.name }}</a> {% endif %} {% endfor %} </dd> </dl> <dl class="clearfix"> <dt>难度:</dt> <dd id="surface_status"> {% if kwargs.level == 0 %} <a class="selected" href="/videos-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html">全部</a> {% else %} <a href="/videos-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-0.html">全部</a> {% endif %} {% for item in level %} {% if item.0 == kwargs.level %} <a class="selected" href="/videos-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.0 }}.html">{{ item.1 }}</a> {% else %} <a href="/videos-{{ kwargs.direction_id }}-{{ kwargs.classification_id }}-{{ item.0 }}.html">{{ item.1 }}</a> {% endif %} {% endfor %} </dd> </dl> </div> </div>