组合搜索组件

我们都会写博客,写文章之后我们要给文章设置目录,设置类型。之后我们在浏览文章的时候就能够按类别进行精确定位到文章,那这个组合搜索我们应该怎么做呢?

首先我们先创建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))
View Code

 

在这里面,我们设置函数,然后接受前端传过来的参数,编写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>
View Code

 

首先要引入这个自定义的模板标签: {% load filter%}

然后给函数传参数