首页 > 代码库 > django多条件筛选搜索(项目实例)

django多条件筛选搜索(项目实例)

多条件搜索在很多网站上都有用到,比如京东,淘宝,51cto,等等好多购物教育网站上都有,当然网上也有很多开源的比楼主写的好的多了去了,仅供参考,哈哈

先来一张效果图吧,不然幻想不出来是什么样的,前端样式很low,毕竟主要是说后台的嘛,前端为了简单测试就简单的写出来啦,喜欢好的样式可以自己去调哈

技术分享

写后台的应该都知道先从数据库方面入手,所以我们先来设计数据库

 

数据库设计

1、视频video

class Video(models.Model):    status_choice = (        (0, u下线),        (1, u上线),    )    level_choice = (        (1, u初级),        (2, u中级),        (3, u高级),    )    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=256)    create_date = models.DateTimeField(auto_now_add=True)    class Meta:        db_table = Video        verbose_name_plural = u视频    def __str__(self):        return self.title

2、视频方向Direction

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 = u方向(视频方向)    def __str__(self):        return self.name

3、视频分类Classification

class Classification(models.Model):    weight = models.IntegerField(verbose_name=权重(按从大到小排列), default=0)    name = models.CharField(verbose_name=名称, max_length=32)    class Meta:        db_table = Classification        verbose_name_plural = u分类(视频分类)    def __str__(self):        return self.name

好了大家一起来分析下数据库设计

  • 视频方向Direction类和视频分类Classification多对多关系,因为一个视频方向可以有多个分类,一个视频分类也可以有多个视频方向视频分类

  • Classification视频分类和视频Video类是一对多关系,因为一个分类肯定有好多视频

  • 视频Video类中level_choice 与视频也是一对多关系,因为这个也就这三个分类,所以我选择把他放在内存里面取,毕竟这玩意常年不会变

 

url映射

from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [    url(r^admin/, admin.site.urls),    url(r^video-(?P<direction_id>\d+)-(?P<classification_id>\d+)-(?P<level_id>\d+).html, views.video),]

输入的url为:http://127.0.0.1:8080/video-0-0-0.html

  • 中间第一个0代表视频方向,第二个0代表食品分类,第三个0是视频等级,这个是根据汽车之间那个二手车学的,用着很方便哈哈

  • 0代表全部,然后递增,当选择运维自动化,第一个0就会变成1

  • 下面那些都是一样的道理

 

前端代码

前端HTML,有用到django的simple_tag,从总体效果图可以看出,前端主要分为两部分,选择部分和视频展示部分

1、选择部分

    <h3>选择:</h3>    <div>        {% action_all current_url 1 %} :        {% for item in direction_list %}             {% action current_url item %}        {% endfor %}    </div>    <div>        {% action_all current_url 2 %} :        {% for item in class_list %}            {% action current_url item %}        {% endfor %}    </div>    <div>        {% action_all current_url 3 %} :        {% for item in level_list %}            {% action current_url item %}        {% endfor %}    </div>

中间主要是用simple_tag来做的前端代码

@register.simple_tagdef action_all(current_url,index):    """    获取当前url,video-1-1-2.html    :param current_url:    :param item:    :return:    """    url_part_list = current_url.split(-)    if index == 3:        if url_part_list[index] == "0.html":            temp = "<a href=http://www.mamicode.com/‘%s‘ class=‘active‘>全部"        else:            temp = "<a href=http://www.mamicode.com/‘%s‘>全部"        url_part_list[index] = "0.html"    else:        if url_part_list[index] == "0":            temp = "<a href=http://www.mamicode.com/‘%s‘ class=‘active‘>全部"        else:            temp = "<a href=http://www.mamicode.com/‘%s‘>全部"        url_part_list[index] = "0"    href = -.join(url_part_list)    temp = temp % (href,)    return mark_safe(temp)@register.simple_tagdef action(current_url, item,index):    # videos-0-0-1.html    # item: id name    # video-   2   -0-0.html    url_part_list = current_url.split(-)     if index == 3:        if str(item[id]) == url_part_list[3].split(.)[0]:  #如果当前标签被选中             temp = "<a href=http://www.mamicode.com/‘%s‘ class=‘active‘>%s"        else:            temp = "<a href=http://www.mamicode.com/‘%s‘>%s"         url_part_list[index] = str(item[id]) + .html #拼接对应位置的部分url    else:        if str(item[id]) == url_part_list[index]:            temp = "<a href=http://www.mamicode.com/‘%s‘ class=‘active‘>%s"        else:            temp = "<a href=http://www.mamicode.com/‘%s‘>%s"         url_part_list[index] = str(item[id])     ur_str = -.join(url_part_list)  #拼接整体url    temp = temp %(ur_str, item[name]) #生成对应的a标签    return mark_safe(temp)  #返回安全的html

 

2、视频展示区域

    <h3>视频:</h3>    {% for item in video_list %}        <a class="item" href="{{ item.href }}">            <img src="/{{ item.img }}" width="300px" height="400px">            <p>{{ item.title }}</p>            <p>{{ item.summary }}</p>        </a>    {% endfor %}

关键来啦关键来啦,最主要的处理部分在这里,往这看,往这看,往这看,主要的事情说三遍哈

视频后台逻辑处理部分

def video(request,*args,**kwargs):    print(kwargs)    # 当前请求的路径    request_path = request.path    # 从数据库获取视频时的filter条件字典    q = {}    # 状态为审核通过的    q[status] = 1    # 获取url中的视频分类id    class_id = int(kwargs.get(classification_id))    # 从数据库中获取所有的视频方向(包括视频方向的id和name)    direction_list = models.Direction.objects.all().values(id,name)    # 如果视频方向是0    if kwargs.get(direction_id) == 0:        # 方向选择全部        # 方向id=0,即获取所有的视频分类(包括视频分类的id和name)        class_list = models.Classification.objects.all().values(id, name)        # 如果视频分类id也为0,即全部分类,那就什么都不用做,因为已经全取出来了        if kwargs.get(classification_id) == 0:            pass        else:            # 如果视频分类不是全部,过滤条件为视频分类id在[url中的视频分类id]            q[classification_id__in] = [class_id,]    else:        print(方向不为0)        # 方向选择某一个方向,        # 如果分类是0        if kwargs.get(classification_id) == 0:            print(分类为0)            # 获取已选择的视频方向            obj = models.Direction.objects.get(id=int(kwargs.get(direction_id)))            # 获取该方向的所有视频分类            class_list = obj.classification.all().values(id, name)            # 获取所有视频分类对应的视频分类id            id_list = list(map(lambda x: x[id], class_list))            # 过滤条件为视频分类id in [该方向下的所有视频分类id]            q[classification_id__in] = id_list         else:            # 方向不为0,分类也不为0            obj = models.Direction.objects.get(id=int(kwargs.get(direction_id)))            class_list = obj.classification.all().values(id, name)            id_list = list(map(lambda x:x[id], class_list))            # 过滤条件为视频分类id in [已经选择的视频分类id]            q[classification_id__in] = [class_id,]             print(分类不为0)            # 当前分类如果在获取的所有分类中,则方向下的所有相关分类显示            # 当前分类如果不在获取的所有分类中,            if int(kwargs.get(classification_id)) in id_list:                pass            else:                print(不再,获取指定方向下的所有分类:选中的回到全部)                url_part_list = request_path.split(-)                url_part_list[2] = 0                request_path = -.join(url_part_list)    # 视频等级id    level_id = int(kwargs.get(level_id))    if level_id == 0:        pass    else:        # 过滤条件增加视频等级        q[level] = level_id     # 取出相对应的视频    video_list = models.Video.objects.filter(**q).values(title,summary, img, href)    # 把视频等级转化为单个标签是字典格式,整体是列表格式    ret = map(lambda x:{"id": x[0], name: x[1]}, models.Video.level_choice)    level_list = list(ret)    return render(request, video.html, {direction_list: direction_list,                                          class_list: class_list,                                          level_list: level_list,                                          current_url: request_path,                                          "video_list": video_list})

 

django多条件筛选搜索(项目实例)