云标签比较简单,我们就先来说云标签把

首先我们得先修改models,增加一个Tag表,然后以多对多的方式关联Article,也就是说一篇文章会有多个标签,一个标签下会有多篇文章。

class Tag(models.Model):
    name = models.CharField('标签名', max_length=20)
    created_time = models.DateTimeField('创建时间', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改时间', auto_now=True)    def __unicode__(self):
        return self.name

然后在Article表中增加一个多对多的键

category = models.ForeignKey('Category', verbose_name='分类',                             null=True, default='其他',
                             on_delete=models.SET_NULL)
tag = models.ManyToManyField('Tag', verbose_name='标签集合', blank=True)

接着我们修改视图,新增一个tagview视图,大家可以看出和index视图很像,因为我们直接用的index.html,只是第一个文章列表articlelist不一样

def tag_view(request, tag_id):
    article_list = Article.objects.filter(tag__id=tag_id)
    category_list = Category.objects.all().order_by('name')
    tag_list = Tag.objects.all().order_by('name')    for tag in tag_list:
        tag.length = len(Article.objects.filter(tag__id=tag.id))    return render(request, 'article/index.html', {'article_list': article_list, 'category_list': category_list,                                                  'tag_list': tag_list})

当然index视图也要改变

def index(request):
    article_list = Article.objects.all()
    category_list = Category.objects.all().order_by('name')
    tag_list = Tag.objects.all().order_by('name')    for tag in tag_list:
        tag.length = len(Article.objects.filter(tag__id=tag.id))    return render(request, 'article/index.html', {'article_list': article_list, 'category_list': category_list,                                                  'tag_list': tag_list})

其实和上面差别不大。。。

接下来就是修改模板文件index.html了

    <div class="panel panel-default">
        <div class="panel-heading">标签</div>
        <div class="panel-body">
            {% for tag in tag_list %}                    <a href="{% url 'tag' tag.id %}"></a>
                <a href="{% url 'tag' tag.id %}" class="btn btn-info tag_list">{{ tag.name }}<span class="badge">{{ tag.length }}</span></a>
            {% endfor %}        </div>
    </div>{% endblock %}

我们新增加一个面板用来显示我们的云标签

最后增加一个url就可以啦~

url(r'^tag/(?P<tag_id>\d+)$', tag_view, name='tag'),

文章归类

下来就是按时间对文章进行归类

在具体实施之前得介绍几个概念,首先时datetimes函数,这个函数可以选出数据库中某个model对应的全部已去重的时间,并且可以任意指定精度。我们可以精确到年,月,或者日等等

date_list = Article.objects.datetimes('create_time', 'month', order='DESC') create_time是Article中文章的发表时间,month表示精确到月,DESC表示降序排列,默认时升序 还有个东东就是管理器(Manager)。是django中很重要的一坨

管理器是django的模型进行数据库查询操作的接口,Django应用的每个模块都拥有至少一个管理器,默认情况下,django为每个模型类增加一个名为objects的管理器,我们可以在模型中使用自定义的管理器,方法时继承Manager基类并实例化自定义的管理器。 这里还用到python的一个模块,collections模块中有一个defaultdice()经常被用到, 这里的defaultdict(functionfactory)构建的是一个类似dictionary的对象,其中keys的值,自行确定赋值,但是values的类型,是functionfactory的类实例,而且具有默认值。比如default(int)则创建一个类似dictionary对象,里面任何的values都是int的实例,而且就算是一个不存在的key, d[key] 也有一个默认值,这个默认值是int()的默认值0.如果不是很明白就给大家一个链接defaultdice

首先我们得扩展Manager类,也就是继承并加入新的方法

class ArticleManager(models.Manager):#放在所有models前面
    def archive(self):
        date_list = Article.objects.datetimes('create_time', 'month', order='DESC')        # 获取到降序排列的精确到月份且已去重的文章发表时间列表
        # 并把列表转为一个字典,字典的键为年份,值为该年份下对应的月份列表
        date_dict = defaultdict(list)        for d in date_list:
            date_dict[d.year].append(d.month)         # 模板不支持defaultdict,因此我们把它转换成一个二级列表,由于字典转换后无序,因此重新降序排序
        return sorted(date_dict.items(), reverse=True)

自定义了Manger后需要在model中显示的指示它:

article/models.pyclass Article(models.model):
    ...    # 仍然使用默认的 objects 作为 manager 的名字
    objects = ArticleManager()
    ...

现在我们在视图中就可以调用了

def index(request):
    article_list = Article.objects.all()
    category_list = Category.objects.all().order_by('name')
    tag_list = Tag.objects.all().order_by('name')
    date_archive = Article.objects.archive()    for tag in tag_list:
        tag.length = len(Article.objects.filter(tag__id=tag.id))    return render(request, 'article/index.html', {'article_list': article_list, 'category_list': category_list,                                                  'tag_list': tag_list, 'date_archive': date_archive})

然后我们在模板中把它渲染出来

{% for year,month_list in date_archive %}
    `year` 年
    {% for month in month_list %}
        `month`月
    {% endfor %}
{% endfor %}

当然,这只是显示出来时间的列表,我们是想通过点击时间,然后列出这个时间段下的所有文章。我们来开始实现它! 首先我们先增加一个视图,如下:

def archive_view(request, year, month):
    article_list = Article.objects.filter(create_time__year=int(year), create_time__month=int(month))
    category_list = Category.objects.all().order_by('name')
    tag_list = Tag.objects.all().order_by('name')
    date_archive = Article.objects.archive()    for tag in tag_list:
        tag.length = len(Article.objects.filter(tag__id=tag.id))    return render(request, 'article/index.html', {'article_list': article_list, 'category_list': category_list,                                                  'tag_list': tag_list, 'date_archive': date_archive})

接下来我们新增一个url咯

url(r'^archive/(?P<year>\d+)/(?P<month>\d+)/$', archive_view, name='archive'),

然后我们在index.html中从新渲染~

<div class="panel panel-default">
    <div class="panel-heading">标签</div>
    <div class="panel-body">
        {% for year,month_list in date_archive %}
            `year` 年
            {% for month in month_list %}                <a href="{% url 'archive' year month %}"><p>{{ month }} 月</p></a>
            {% endfor %}
        {% endfor %}    </div></div>

不懂地方,问博主哈~~~ 博主邮件:690347460@qq.com 本系列文章,参考自:

  1. 编程派

  2. 开篇

  3. 详细视图

  4. 文章列表分页和代码语法高亮

  5. 基于类的通用视图

  6. 标签云与文章归档 文章评论