一、前言
我们学习一下组合搜索组件,我们在筛选内容的时候会经常用到,这边我们就来一个初版,因为这个后面还需要进行进一步优化,下面我们就来看看,我们这搜索组件是咋写的,这个东西我们会经常用到的,所以要认真的写一下,我们来根据汽车之家的效果图:
以上是汽车之家的页面,我们也是照着汽车之家的格式写一个,写成一个,以:http://127.0.0.1:8000/article-2-4.html 这样的方式访问。
二、组合搜索组件
2.1、模型(model)
说明:是数据库的设置,这个里面的数据都是自己填写的,后面我们贴出来了,创建数据库之前需要执行python manage.py makemigrations和 python manage.py migrate。
from django.db import modelsclass Category(models.Model): """ 文章分类表 """ caption = models.CharField(max_length=16)class ArticleType(models.Model): """ 文章类型表 """ caption = models.CharField(max_length=16)class Article(models.Model): """ 文章表 """ title = models.CharField(max_length=32) content = models.CharField(max_length=255) category = models.ForeignKey(Category,on_delete=models.CASCADE) article_type = models.ForeignKey(ArticleType,on_delete=models.CASCADE)
数据创建如下:
2.2、路由的设置(urls)
说明:我们在路由里面设置两个参数,因为我们在访问的时候,通过类似:http://127.0.0.1:8000/article-2-4.html(2:文章类型id,4:文章分类id)
from django.urls import path,re_pathfrom app01 import viewsurlpatterns = [ re_path(r'^article-(?P\d+)-(?P \d+).html$',views.article,name='article')]
2.3、article函数编写
说明:编写article函数传文章对象,文章类型和文章分类对象过去,还有前端通过 传 article_type_id 和 category_id 到前端
from django.shortcuts import renderfrom app01 import modelsdef article(request,*args,**kwargs): # print(kwargs) #{'category_id': '0', 'article_type_id': '0'} # print(request.path_info) # from django.urls import reverse # url = reverse('article',kwargs=kwargs) #用name+参数 可以生成指定url # print(url) condition = {} #如果显示全部的话,则显示所有文章 for k,v in kwargs.items(): kwargs[k] = int(v) #需要把value的值转化为整数,跟后面的id数据类型一样 if v == '0': pass else: condition[k] = v #获取传过来的article_type_id 和 category_id article_type_list = models.ArticleType.objects.all() catagory_list = models.Category.objects.all() result = models.Article.objects.filter(**condition) #两个article_type_id 和 category_id组合成一个条件帮我筛选文章 return render(request,'article.html', { 'result':result, 'article_type_list':article_type_list, #文章类型 'catagory_list':catagory_list, #文章分类 'arg_dict':kwargs, #传过来的 article_type_id 和 category_id } )
2.4、article.html模板
说明:article函数获取的数据全部映射到article.html模板上
Title 过滤条件
{% if arg_dict.article_type_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for row in article_type_list %} {% if row.id == arg_dict.article_type_id %} { { row.caption }} {% else %} { { row.caption }} {% endif %} {% endfor %}{% if arg_dict.category_id == 0 %} 全部 {% else %} 全部 {% endif %} {% for row in catagory_list %} {% if row.id == arg_dict.category_id %} { { row.caption }} {% else %} { { row.caption }} {% endif %} {% endfor %}查询结果
- {% for row in result %}
- { { row.id }}-{ { row.title }} {% endfor %}
注意:中间的逻辑思想已经写入article.html模板语言中。
我们生成的效果图如下:
三、优化article.html(simple_tag方式)
有些同学就说了,你上面article.html模板写的太啰嗦了,能不能有简单的方式呐,有的,我们今天就用我们学过的知识点 simple_tag 的方式来改一下,具体 simple_tag 如何使用,请查看:http://www.cnblogs.com/zhangqigao/articles/8658579.html,这边我专门写了一篇博客出来,好啦,下面我们就来改造吧!
3.1、创建simple_tag函数
说明:app01->创建templatetags文件夹->创建filter.py文件,三个函数:filter_all(过滤全部)、filter_article_type(过滤文章类型)、filter_category_type(过滤文章分类),三个分别对应的上面article.html中的过滤。
from django import templatefrom django.utils.safestring import mark_saferegister = template.Library() #这个register对象名字也不能是其他名字,只能叫register@register.simple_tagdef filter_all(arg_dict,k): """ 过滤全部选项 :param arg_dict: :param k: :return: """ #假设我们只有article_type_id和category_id if k == "article_type_id": #传入article_type_id n1 = arg_dict['article_type_id'] n2 = arg_dict['category_id'] if n1 == 0: ret = '全部'%n2 else: ret = '全部'%n2 else: n1 = arg_dict['category_id'] #category_id n2 = arg_dict['article_type_id'] if n1 == 0: ret = '全部'%n2 else: ret = '全部'%n2 return mark_safe(ret)@register.simple_tagdef filter_article_type(article_type_list,arg_dict): """ 过滤文章类型 :param article_type_list: :param arg_dict: :return: """ ret = list() for row in article_type_list: if row.id == arg_dict['article_type_id']: temp = '%s'%(row.id,arg_dict['category_id'],row.caption,) else: temp = '%s'%(row.id,arg_dict['category_id'],row.caption,) ret.append(temp) return mark_safe(''.join(ret))@register.simple_tagdef filter_category_type(catagory_list,arg_dict): """ 过滤文章目录 :param catagory_list: :param arg_dict: :return: """ ret = list() for row in catagory_list: if row.id == arg_dict['category_id']: temp = '%s'%(arg_dict['article_type_id'],row.id,row.caption,) else: temp = '%s'%(arg_dict['article_type_id'],row.id,row.caption,) ret.append(temp) return mark_safe(''.join(ret))
3.2、article.html改进
说明:我们这边需要导入filter模块,然后再使用函数
{% load filter %}Title 过滤条件
{% filter_all arg_dict 'article_type_id'%} {% filter_article_type article_type_list arg_dict %}{% filter_all arg_dict 'category_id'%} {% filter_category_type catagory_list arg_dict %}查询结果
- {% for row in result %}
- { { row.id }}-{ { row.title }} {% endfor %}
显示的效果图和上面的一模一样
四、文章分类放内存
之前我们文章分类的数据是放在数据库的,那如果我们的文章分类是放在内存中,我们如何改进呐?
4.1、model的改进
说明:数据库的改进,我们增加choice选项,代替原来的外键
from django.db import modelsclass Category(models.Model): """ 文章分类表 """ caption = models.CharField(max_length=16)class Article(models.Model): """ 文章表 """ title = models.CharField(max_length=32) content = models.CharField(max_length=255) category = models.ForeignKey(Category,on_delete=models.CASCADE) #把表改成内存级别的,因为这几个是不变的东西 type_choice = ( (1,'Python'), (2,'Openstack'), (3,'Linux'), ) article_type_id = models.IntegerField(choices=type_choice)
4.2、article函数改进
说明:文章分类对象是直接从内存中去获取的,而不是重另外一张表中获取
from django.shortcuts import renderfrom app01 import modelsdef article(request,*args,**kwargs): condition = {} #如果显示全部的话,则显示所有文章 for k,v in kwargs.items(): kwargs[k] = int(v) if v == '0': pass else: condition[k] = v article_type_list = models.Article.type_choice #article_type_list=((1, 'Python'), (2, 'Openstack'), (3, 'Linux')) catagory_list = models.Category.objects.all() result = models.Article.objects.filter(**condition) return render(request,'article.html', { 'result':result, 'article_type_list':article_type_list, 'catagory_list':catagory_list, 'arg_dict':kwargs, } )
4.3、filter模块中filter_article_type改进
说明:因为是一个article_type_list是一个数组类型的,所以获取row.id和row.caption,就会变成row[0],row[1]
@register.simple_tagdef filter_article_type(article_type_list,arg_dict): """ 过滤文章类型 :param article_type_list: :param arg_dict: :return: """ ret = list() for row in article_type_list: #article_type_list=((1, 'Python'), (2, 'Openstack'), (3, 'Linux')) if row[0] == arg_dict['article_type_id']: temp = '%s'%(row[0],arg_dict['category_id'],row[1],) else: temp = '%s'%(row[0],arg_dict['category_id'],row[1],) ret.append(temp) return mark_safe(''.join(ret))
显示的效果图: