Diango博客--解锁博客侧栏

£可爱£侵袭症+ 提交于 2019-12-09 21:58:17

0.思路引导

博客侧边栏有四项内容:最新文章、归档、分类和标签云,效果展示如下:
在这里插入图片描述

这些内容相对比较固定和独立,且在各个页面都会显示,如果像文章列表或者文章详情一样,从视图函数中获取这些数据然后传递给模板,则每个页面对应的视图函数里都要写一段获取这些内容的代码,这会导致很多重复代码。

更好的解决方案是直接在模板中获取,为此,我们使用 django 的一个新技术:自定义模板标签来完成任务。

我们前面已经接触过一些 django 内置的模板标签,比如比较简单的 {% static %} 模板标签,这个标签帮助我们在模板中引入静态文件。还有比较复杂的如 {% for %} {% endfor%} 标签。

这里我们希望自己定义一个模板标签,例如名为 show_recent_posts 的模板标签,它可以这样工作:我们只要在模板中写入 {% show_recent_posts %},那么模板中就会渲染一个最新文章列表页面,这和我们在编写博客首页面视图函数是类似的。

首页视图函数中从数据库获取文章列表并保存到 post_list 变量,然后把这个 post_list 变量传给模板,模板使用 for 模板标签循环这个文章列表变量,从而展示一篇篇文章。

这里唯一的不同是我们从数据库获取文章列表的操作不是在视图函数中进行,而是在模板中通过自定义的 {% show_recent_posts %} 模板标签进行。

1.[最新文章] 模板标签

首先在 blog 应用下创建一个 templatetags 文件夹。然后在这个文件夹下创建一个 init.py 文件,使这个文件夹成为一个 Python 包,之后在 templatetags\ 目录下创建一个 blog_extras.py 文件,这个文件存放自定义的模板标签代码。
文件位置:blog/templatetags/blog_extras.py

from django import template

from ..models import Post, Category, Tag

register = template.Library()


@register.inclusion_tag('blog/inclusions/_recent_posts.html', takes_context=True)
def show_recent_posts(context, num=5):
    return {
        'recent_post_list': Post.objects.all().order_by('-created_time')[:num],
    }

这里我们首先导入 template 这个模块,然后实例化了一个 template.Library 类,并将函数 show_recent_posts 装饰为 register.inclusion_tag,这样就告诉 django,这个函数是我们自定义的一个类型为 inclusion_tag 的模板标签。

inclusion_tag 模板标签和视图函数的功能类似,它返回一个字典值,字典中的值将作为模板变量,传入由 inclusion_tag 装饰器第一个参数指定的模板blog/inclusions/_recent_posts.html。

当我们在模板中(base.html)通过 {% show_recent_posts %}使用自己定义的模板标签时,django 会将指定模板的内容使用模板标签 {% show_recent_posts %}返回的模板变量渲染后替换。

接下来就是定义模板 _recent_posts.html 的内容。在 templates\blogs 目录下创建一个 inclusions 文件夹,然后创建一个 _recent_posts.html 文件,内容如下:

文件位置:templates\blogs\inclusions _recent_posts.html

<div class="widget widget-recent-posts">
  <h3 class="widget-title">最新文章</h3>
  <ul>
    {% for post in recent_post_list %}
      <li>
        <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
      </li>
    {% empty %}
      暂无文章!
    {% endfor %}
  </ul>
</div>

循环由{% show_recent_posts %}传递的模板变量 recent_post_list 即可,和 index.html 中循环显示文章列表是一样的。

2.[归档] 模板标签

和上一部分类似,接下来对其余部分代码进行补充。

文件位置:blog/templatetags/blog_extras.py

@register.inclusion_tag('blog/inclusions/_archives.html', takes_context=True)
def show_archives(context):
    return {
        'date_list': Post.objects.dates('created_time', 'month', order='DESC'),
    }

文件位置:templates\blogs\inclusions _archives.html

<div class="widget widget-archives">
  <h3 class="widget-title">归档</h3>
  <ul>
    {% for date in date_list %}
      <li>
        <a href="#">{{ date.year }}{{ date.month }}</a>
      </li>
    {% empty %}
      暂无归档!
    {% endfor %}
  </ul>
</div>

3.[分类] 模板标签

文件位置:blog/templatetags/blog_extras.py

@register.inclusion_tag('blog/inclusions/_categories.html', takes_context=True)
def show_categories(context):
    return {
        'category_list': Category.objects.all(),
    }

文件位置:templates\blogs\inclusions _categories.html

<div class="widget widget-category">
  <h3 class="widget-title">分类</h3>
  <ul>
    {% for category in category_list %}
      <li>
        <a href="#">{{ category.name }} <span class="post-count">(13)</span></a>
      </li>
    {% empty %}
      暂无分类!
    {% endfor %}
  </ul>
</div>

4.[标签云] 模板标签

文件位置:blog/templatetags/blog_extras.py

@register.inclusion_tag('blog/inclusions/_tags.html', takes_context=True)
def show_tags(context):
    return {
        'tag_list': Tag.objects.all(),
    }

文件位置:templates\blogs\inclusions _tags.html

<div class="widget widget-tag-cloud">
  <h3 class="widget-title">标签云</h3>
  <ul>
    {% for tag in tag_list %}
      <li>
        <a href="#">{{ tag.name }}</a>
      </li>
    {% empty %}
      暂无标签!
    {% endfor %}
  </ul>
</div>

5.使用自定义的模板标签

打开 base.html,为了使用刚才定义的模板标签,我们首先需要在模板中导入存放这些模板标签的模块,这里是 blog_extras.py 模块。当时我们为了使用 static 模板标签时曾经导入过 {% load static %},这次在 {% load static %} 下再导入 blog_extras:

文件位置:templates/base.html


{% load static %}
{% load blog_extras %}
<!DOCTYPE html>
<html>
...
</html>

然后找到侧边栏各项,将他们都替换成对应的模板标签:

文件位置:templates/base.html


<aside class="col-md-4">
  {% block toc %}
  {% endblock toc %}

  {% show_recent_posts %}
  {% show_archives %}
  {% show_categories %}
  {% show_tags %}

  <div class="rss">
     <a href=""><span class="ion-social-rss-outline"></span> RSS 订阅</a>
  </div>
</aside>

此前侧边栏中各个功能块都替换成了模板标签,其实实际内容还是一样的,只是我们将其挪到了模块化的模板中,并有这些自定义的模板标签负责渲染这些内容。

此外我们定义的 show_recent_posts 标签可以接收参数,默认为 5,即显示 5 篇文章,如果要控制其显示 10 篇文章,可以使用 {% show_recent_posts 10 %} 这种方式传入参数。

现在运行开发服务器,可以看到侧边栏显示的数据已经不再是之前的占位数据,而是我们保存在数据库中的数据了。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!