PyxYuYu/MyBlog

Django学习记录(十九):Django by example -- Blog(十五)

PyxYuYu opened this issue · 0 comments

I always like walking in the rain, so no one can see me crying.

0x01 Django

  • Build a Blog Application
    • Creating custom template tags
    • 创建自定义的模板标签
    • Django 提供了很多内建的模板标签,比如 {% if %} {% block %} 等,然而 Django 也允许我们创建自定义的模板标签来执行行为
    • Django 提供了以下几个函数来创建:
      • simple_tag 接受数据返回一个字符串
      • inclusion_tag 通过渲染其他模板显示数据
      • assignment_tag 接受数据并且在 context 中设置
    • 模板标签必须存在于 Django app 中,也就是模板标签必须绑定 app,该 app 应该包含一个 templatetags 目录,该目录存在于 blog app 下,和 models.py views.py 同一层级,在其中新建一个 __init__.py 空文件,这样 Django 可认为是一个 Python
    • 在该目录下,新建一个 Python 模块文件: blog_tags.py 结构如下
       blog/
           __init__.py
     	  models.py
     	  ...
     	  templatetags/
     	      __init__.py
     		  blog_tags.py
    • 在模板文件中就可以导入 blog_tags.py 来使用自定义标签
       {% load blog_tags %}
    • 接下来创建一个简单的标签用于检索所有公开的 posts,编辑 blog_tags.py
       from django import template
       
       register = template.Library()
       
       from ..models import Post
       
       @register.simple_tag
       def total_posts():
           return Post.published.count()
    • 每个模板标签模块都需要包含一个名为 register 的变量(一个有效的标签库),这个变量是 template.Library 的实例,用于注册模板标签和过滤器
    • 上面定义了一个标签 total_posts : 用 @register.simple_tag 定义下面的函数为一个简单标签并且注册了它,Django 会用函数名作为标签名,如果要用其他名称可以用
       @register.simple_tag(name='my_tag')
    • 将自定义标签运用到模板中,先用 {% load %} 导入,{% total_posts %} 就是我们的自定义标签,编辑 blog/base.html
       {% load blog_tags %}
       ...
           <p>This is my blog. I've written {% total_posts %} posts so far.</p>
       ...
    • 注意:如果需要使用新的自定义标签或者过滤器的话,需要重新启动开发服务器
    • 上面创建的是简单标签,接下来创建一个包含标签,这个标签用于显示最后更新的 posts
    • 编辑 blog_tags.py 增加
       @register.inclusion_tag('blog/post/latest_posts.html')
       def show_latest_posts(count=2):
           latest_posts = Post.published.order_by('-publish')[:count]
     	  return {'latest_posts': latest_posts}
    • 这里利用 @register.inclusion_tag 注册了模板标签,指定了一个被渲染的模板和其中返回的变量,后面函数接收一个参数 count(默认为2,指定了我们希望显示的数量),函数最后返回的是一个字典
    • 包含标签最后返回的都是一个字典,通常被用作渲染指定的模板,这个模板标签可以传送一个自定义的 count ,比如 {% show_latest_posts 4 %}
    • blog/post/ 下创建一个 latest_posts.html 模板
       <ul>
           {% for post in latest_posts %}
     	      <li>
     		      <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
     		  </li>
     	  {% endfor %}
       </ul>
    • latest_posts.html 模板显示的是没有顺序的 posts 列表,接下来编辑 blog/base.html 模板,添加自定义的标签显示最近更新的3个 posts
       <p>This is my blog. I've written {% total_posts %} posts so far.</p>
       <h3>Latest posts</h3>
       {% show_latest_posts 3 %}
    • 接着创建一个 assignment_tag ,和 simple_tag 类似,最大的区别就是它可以存储标签结果为一个变量去代替直接输出,这样方便前台模板页面对内容的再次处理和展现,如 {% assignment_tag as variable %}
    • 创建 assignment_tag 用于显示评论最多的 posts ,编辑 blog_tags.py ,添加
       from django.db.models import Count
       
       @regiest assignment_tag
       def get_most_commented_posts(count=2):
           return Post.published.annotate(total_comments=Count('comments')).order_by('-total_comments')[:count]
    • 利用聚合函数,通过统计 posts 数量来获得评论的数量 total_comments
    • 编辑 blog/base.html 模板,添加在 show_latest_posts
       <h3>Most commented posts</h3>
       {% get_most_commented_posts as most_commented_posts %}
       <ul>
       {% for post in most_commented_posts %}
           <li>
     	      <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
     	  </li>
       {% endfor %}
       </ul>
    • 注意:简单标签返回的是一个字符串,而 assignment_tag 重新定义后可以如上所示成为一个列表