当前位置: 首页 > 后端技术 > Python

HelloDjango第12部分:解锁博客侧边栏,GoGoGo!

时间:2023-03-26 14:56:37 Python

作者:HelloGitHub-追梦人文中涉及的示例代码已更新至HelloGitHub-Team仓库。我们博客的侧边栏中有四个项目:最新文章、档案、类别和标签云。这些内容是相对固定和独立的,会在每个页面上展示。如果像文章列表或者文章详情这样的数据是从视图函数中获取并传给模板的,那么每个页面对应的视图函数中都要写一个段落。为这些内容编写代码,这就造成了大量的重复代码。更好的方案是直接在模板中获取。为此,我们使用django的一项新技术:自定义模板标签来完成任务。使用模板标签的解决方案我们已经接触过一些Django内置的模板标签,比如比较简单的{%static%}模板标签,它可以帮助我们在模板中引入静态文件。还有更复杂的标签,例如{%for%}{%endfor%}。这里我们要自己定义一个模板标签,比如一个名为show_recent_posts的模板标签,它可以这样工作:我们只需要在模板中写{%show_recent_posts%},那么就会渲染一个最新的文章列表页面template,这个和我们写博客首页的view功能类似。在首页视图函数中,从数据库中获取文章列表并保存到post_list变量中,然后将post_list变量传递给模板。该模板使用for模板标记循环遍历文章列表变量以显示每篇文章。这里唯一的区别是我们不是在视图函数中,而是通过自定义{%show_recent_posts%}模板标签在模板中从数据库中获取文章列表。以上是解决方法,但是模板标签不是随便写的。它们必须遵循django规范才能在django模板系统中使用。下面将根据这些规范来实现我们的要求。模板标签目录结构首先在我们的博客应用下创建一个templatetags文件夹。然后在这个文件夹下创建一个__init__.py文件使这个文件夹成为一个Python包,然后在templatetags目录下创建一个blog_extras.py文件,里面存放自定义的模板标签代码。此时你的目录结构应该是这样的:blog\__init__.pyadmin.pyapps.pymigrations\__init__.pymodels.pystatic\templatetags\__init__.pyblog_extras.pytests.pyviews.pywritetemplate标签代码接下来就是编写各个模板标签的代码,自定义模板标签代码写在blog_extras.py文件中。其实一个模板标签本质上就是一个Python函数,所以按照一个Python函数的思路写模板标签的代码就可以了,并没有什么新意和新知识在里面。最新帖子模板标签打开blog_extras.py文件并开始编写我们的最新帖子模板标签。fromdjangoimporttemplatefrom..modelsimportPost,Category,Tagregister=template.Library()@register.inclusion_tag('blog/inclusions/_recent_posts.html',takes_context=True)defshow_recent_posts(context,num=5):返回{'recent_post_list':Post.objects.all().order_by('-created_time')[:num],}这里我们先导入模板模块,然后实例化一个template.Library类,将函数show_recent_posts装饰成register。inclusion_tag,它告诉django这个函数是一个类型为inclusion_tag的自定义模板标签。inclusion_tag模板标签与视图函数有类似的功能。它返回一个字典值。字典中的值将用作模板变量并传递给inclusion_tag装饰器的第一个参数指定的模板。当我们通过{%show_recent_posts%}在模板中使用自己定义的模板标签时,django会渲染并用模板标签返回的模板变量替换指定模板的内容。当inclusion_tag装饰器的参数takes_context设置为True时,会告诉django在渲染_recent_posts.html模板时,不仅会传入show_recent_posts返回的模板变量,还会传入父模板(即,使用{%show_recent_posts%}模板标签的模板)上下文(可以简单理解为渲染父模板的视图函数传递给父模板的模板变量和django自身传递的模板变量)。当然,这里不使用这个上下文。这里只是一个简单的演示。如果需要使用,可以在模板标签函数的定义中使用上下文变量来引用这个上下文。下一步是定义模板_recent_posts.html的内容。在templatesblogs目录下创建一个inclusions文件夹,然后创建一个_recent_posts.html文件,内容如下:Latestarticles

    {%forpostinrecent_post_list%}
  • {{post.title}}
  • {%empty%}暂时没有文章!{%endfor%}
很简单,就是循环show_recent_posts传过来的模板变量recent_post_list,和index.html中的文章列表循环一样。存档模板标签和最新文章模板标签一样,先写函数,再把函数注册为模板标签。@register.inclusion_tag('blog/inclusions/_archives.html',takes_context=True)defshow_archives(context):return{'date_list':Post.objects.dates('created_time','month',order='DESC'),}这里的Post.objects.dates方法会返回一个列表,列表中的元素是每篇文章(Post)的创建时间(已移除),是一个Python日期对象,精确到月份,排序在降序。接受的三个参数值表示这几个意思,一个是created_time,即Post的创建时间,month是精度,order='DESC'表示降序(即越接近post的时间当前时间排在第一位)。比如我们写了3篇文章,分别发表于2017年2月21日、2017年3月25日、2017年3月28日,那么dates函数会返回2017年3月和2017年2月的时间列表,并降序排列,从而帮助我们达到每月归档的目的。然后是渲染模板_archives.html的内容:Archive
    {%fordateindate_list%}
  • {{date.year}}年{{date.month}}月
  • {%empty%}还没有存档!{%endfor%}
由于date_list中的每个元素都是一个Python日期对象,所以可以参考year和month属性来获取年月。模板标签分类的过程还是一样的,先写函数,然后把函数注册为模板标签。注意分类模板标签函数中使用了Category类,定义在blog.models.py文件中。使用前记得导入,否则会报错。@register.inclusion_tag('blog/inclusions/_categories.html',takes_context=True)defshow_categories(context):return{'category_list':Category.objects.all(),}_categories.html的内容:category
    {%forcategoryincategory_list%}
  • {{category.name}}(13)
  • {%empty%}还没有分类!{%endfor%}
(13)显示该分类下的文章数,这个功能会在下个教程中讲解Howto实现它,暂时用占位符数据替换它。标签云模板标签标签和类别其实很相似,模板标签:@register.inclusion_tag('blog/inclusions/_tags.html',takes_context=True)defshow_tags(context):return{'tag_list':Tag.objects.all(),}_tags.html:标签云
    {%fortagintag_list%}
  • {{tag.name}}
  • {%empty%}还没有标签!{%endfor%}
使用自定义模板标签打开base.html。为了使用刚刚定义的模板标签,我们首先需要在模板中导入存放这些模板标签的模块,这里是blog_extras。py模块。当时我们为了使用static模板标签引入了{%loadstatic%},这次我们在{%loadstatic%}下引入了blog_extras:templates/base.html{%loadstatic%}{%loadblog_extras%}...然后在侧边栏中找到项目并替换为相应的模板标签:templates/base.html{%blocktoc%}{%endblocktoc%}{%show_recent_posts%}{%show_archives%}{%show_categories%}{%show_tags%}RSS订阅之前,侧边栏中的每个功能块被替换为模板标签,但实际内容是还是一样。只是我们把它移到了一个模块化的模板中,这些自定义的模板标签负责渲染这些内容。另外,我们定义的show_recent_posts标签可以接收参数,默认为5,即显示5篇文章,如果要控制它显示10篇文章,可以使用{%show_recent_posts10%}传入参数。现在运行开发服务器,可以看到侧边栏显示的数据不再是之前的占位符数据,而是我们保存在数据库中的数据。注意:如果在开发服务器启动时编写模板标签代码,必须重启开发服务器导入blog_extras,否则在/'blog_extras'处出现TemplateSyntaxError不是注册标签库。必须是以下之一:像这样的错误。注意:如果按照教程步骤操作后发现错误,请按以下顺序检查。检查目录结构是否正确。确保templatetags位于博客目录中,目录名称必须是templatetags。详情请参考上面给出的目录结构。确保templatetags目录中有一个__init__.py文件。确保通过register=template.Library()和@register.inclusion_tag装饰器将函数装饰为模板标签。确保在使用模板标签之前导入blog_extras,即{%loadblog_extras%}。在使用blog_extras下的任何模板标签之前,请小心导入它。确保您对模板标签使用正确的语法,即{%loadblog_extras%},注意{and%and%and}之间的任何空格。欢迎关注HelloGitHub公众号获取更多开源项目的资讯和内容。《解释开源项目系列》上线——让对开源项目感兴趣的人不再害怕,让开源项目的发起者不再孤单。关注我们的文章,您将发现编程的乐趣,使用并发现参与开源项目是多么容易。欢迎联系我们投稿,让更多的人爱上开源,为开源做贡献~