组合搜索组件
我们都会写博客,写文章之后我们要给文章设置目录,设置类型。之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢?
首先我们先创建3张表,分别存放文章,文章目录和文章分类:
models.py
#文章目录 class 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)
这里面article要和上面两个表建立外键,以便查询等
urls.py:
urlpatterns = [ url(r'^article-(?P<article_type_id>\d+)-(?P<category_id>\d+).html', views.article,name="article"), ]
设置显示文章的url,在这里面我们要设置url的参数,用来传入选择文章的目录和标签。文章url形如:http://127.0.0.1:8000/article-0-0.html
views.py:
from django.shortcuts import render from app01 import models # Create your views here. def 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.ArticleType.objects.all() category_list = models.Category.objects.all() result = models.Article.objects.filter(**condition) return render(request,'article.html',{'result':result, 'article_type_list':article_type_list, 'category_list':category_list, 'arg_dict':kwargs, } )
在views中我们要获取到用户所有的文章,但是要通过urls上的目录id和分类id的筛选。所以我们可以通过kwargs参数来接收:接受过来的是一个字典形式,比如:{'article_type_id': '0', 'category_id': '0'},这个时候我们就能够进行一系列操作
注意:
- 首先我们要对获取的id进行转换,如果说是0,则选择的时候“全部”,就不需要进行筛选,直接查询所有数据即可;如果不是0,那么就把它赋值到condition这个字典当参数查询
- 我们获得的url的id是字符串的形式,我们前端要用的时候要判断,所以要转换成int类型
- 我们把查询到的数据和获得的url参数中的id传给前台,以便操作
article.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .condition a{ display: inline-block; padding:3px 5px; border: 1px solid #dddddd; margin: 5px; text-decoration: none; } .condition a.active{ background-color: blue; color: white; } </style> </head> <body> <h1>过滤条件</h1> <div class="condition"> <div> {% if arg_dict.article_type_id == 0 %} <a class="active" href="/article-0-{{ arg_dict.category_id }}.html">全部</a> {% else %} <a href="/article-0-{{ arg_dict.category_id }}.html">全部</a> {% endif %} {% for row in article_type_list %} {% if row.id == arg_dict.article_type_id %} <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a> {% else %} <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a> {% endif %} {% endfor %} </div> <div> {% if arg_dict.category_id == 0 %} <a class="active" href="/article-{{ arg_dict.article_type_id }}-0.html">全部</a> {% else %} <a href="/article-{{ arg_dict.article_type_id }}-0.html">全部</a> {% endif %} {% for row in category_list %} {% if row.id == arg_dict.category_id %} <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }}</a> {% else %} <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }}</a> {% endif %} {% endfor %} </div> </div> <h1>查询结果</h1> <ul> {% for row in result %} <li>{{ row.id }}-{{ row.title }}</li> {% endfor %} </ul> </body> </html>
在html中,我们循环出筛选的分类和目录,以及文章。然后设置url,设置a标签的样式等。
需要注意的是:
- 我们要做的样式:选择哪个目录或者分类就要有不同的样式。这样我们就要用if else进行判断。看url中的参数与循环的是否一样。
- 对于选择全部的,我们需要用到views中的int类型的0,做判断。
显示效果:
那我们感觉html写了好多呀,如果这样写的话,那完蛋了,还写死了,重复代码太多了。那怎么办呢?
我们可以用django中自定义模板标签:template_tags
首先在项目下创建一个文件夹template_tags:
然后在filter定义函数:
1 from django import template 2 from django.utils.safestring import mark_safe 3 register = template.Library() 4 5 @register.simple_tag 6 def filter_all(arg_dict,k): 7 ''' 8 {% if arg_dict.article_type_id == 0 %} 9 <a class="active" href="/article-0-{{ arg_dict.category_id }}.html">全部</a> 10 {% else %} 11 <a href="/article-0-{{ arg_dict.category_id }}.html">全部</a> 12 {% endif %} 13 :param arg: 14 :return: 15 ''' 16 ret = "" 17 if k == 'article_type_id': 18 n1 = arg_dict['article_type_id'] 19 n2 = arg_dict['category_id'] 20 if n1 == 0: 21 ret = '<a class="active" href="/article-0-%s.html">全部</a>' % (n2) 22 else: 23 ret = '<a href="/article-0-%s.html">全部</a>' % (n2) 24 else: 25 n1 = arg_dict['category_id'] 26 n2 = arg_dict['article_type_id'] 27 if n1 == 0: 28 ret = '<a class="active" href="/article-%s-0.html">全部</a>' % (n2) 29 else: 30 ret = '<a href="/article-%s-0.html">全部</a>' % (n2) 31 32 return mark_safe(ret) 33 @register.simple_tag 34 def filter_article_type(article_type_list,arg_dict): 35 ''' 36 {% for row in article_type_list %} 37 {% if row.id == arg_dict.article_type_id %} 38 <a class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a> 39 {% else %} 40 <a href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }}</a> 41 {% endif %} 42 {% endfor %} 43 :return: 44 ''' 45 ret = [] 46 for row in article_type_list: 47 if row.id == arg_dict['article_type_id']: 48 temp = '<a class="active" href="/article-%s-%s.html">%s</a>' % (row.id,arg_dict['category_id'],row.caption) 49 else: 50 temp = '<a href="/article-%s-%s.html">%s</a>' % (row.id, arg_dict['category_id'], row.caption) 51 ret.append(temp) 52 return mark_safe("".join(ret)) 53 @register.simple_tag 54 def filter_article_cate(category_list,arg_dict): 55 ''' 56 {% for row in category_list %} 57 {% if row.id == arg_dict.category_id %} 58 <a class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }}</a> 59 {% else %} 60 <a href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }}</a> 61 {% endif %} 62 {% endfor %} 63 :param category_list: 64 :param arg_dict: 65 :return: 66 ''' 67 ret = [] 68 for row in category_list: 69 if row.id == arg_dict['category_id']: 70 temp = '<a class="active" href="/article-%s-%s.html">%s</a>' % (arg_dict['article_type_id'],row.id,row.caption) 71 else: 72 temp = '<a href="/article-%s-%s.html">%s</a>' % (arg_dict['article_type_id'],row.id,row.caption) 73 ret.append(temp) 74 return mark_safe("".join(ret))
在这里面,我们设置函数,然后接受前端传过来的参数,编写HTML,返回到前端
article.html:
1 {% load filter %} 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>Title</title> 7 <style> 8 .condition a{ 9 display: inline-block; 10 padding:3px 5px; 11 border: 1px solid #dddddd; 12 margin: 5px; 13 text-decoration: none; 14 } 15 .condition a.active{ 16 background-color: blue; 17 color: white; 18 } 19 </style> 20 </head> 21 <body> 22 <h1>过滤条件</h1> 23 <div class="condition"> 24 <div> 25 {% filter_all arg_dict 'article_type_id'%} 26 {% filter_article_type article_type_list arg_dict %} 27 </div> 28 <div> 29 {% filter_all arg_dict 'category_id'%} 30 {% filter_article_cate category_list arg_dict %} 31 32 33 </div> 34 </div> 35 36 <h1>查询结果</h1> 37 <ul> 38 {% for row in result %} 39 <li>{{ row.id }}-{{ row.title }}</li> 40 {% endfor %} 41 </ul> 42 43 </body> 44 </html>
首先要引入这个自定义的模板标签: {% load filter%}
然后给函数传参数