
Django - 自定义模板标签
这几天一直在折腾Django的博客项目,今天本想着做完收尾工作就传到Gayhub上,没想到遇一大坑,各种填坑ing……
挖坑
先来简单介绍一下本人亲手挖的坑:
本博客项目templates
中的所有页面都通过block
标签继承自base.html
母模板。其中继承了<title>
、<keywords>
、<discription>
等内容。开发阶段这些内容都是直接写死在base.html
母模板中了,现在准备上线,总不能让用户(假设有用户)去模板中改吧?所以我得将它写到数据库中,让用户可以在后台方便地设置博客的名称
、关键词
、描述
等内容,各大博客也都是这么做的。燃鹅,事情并非那么简单,随之而来的是各种坑,作为处女座代码狗,我TM必须解决……
填坑
尝试了各种方法之后,终于完美解决了问题。用到了自定义模板标签(simple_tag)这个方法。详细解释在后文(踩坑)中,这里只做演示:
在index
应用中新建index_tags.py
文件:
|
在blog
项目下的setting.py
中改写以下几行:
|
在base.html
开头写上以下两行:
|
然后我们就可以在base.html
母模板中使用{{ setting.title }}
、{{ setting.keywords }}
、{{ setting.discription }}
动态渲染数据库中的内容了。
其他页面只需继承base.html
页面即可。例如文章页面
中,描述应该是该文章的摘要,我们就用{% block discription %} {% endblock %}
重载母模板;而标签页面
中,描述无需更改,那就什么都不做呗。
一号坑,重写视图函数
最简单的思路就是在views.py
中的各个视图函数
中调取数据库,然后再渲染到各个模板中,模板中再通过block
标签重写这部分内容。不行,上帝告诉我,不能这么做。一次次地调数据库,渲染模板,重写模板,页面渲染速度拉下一大截。Veto!
二号坑,渲染母模板
稍微拐个弯,很自然的就能想到,我们只需要改写base.html
母模板,动态渲染数据库中的内容即可。Yo, 看似很完美,Thinkphp中就可以用此方法完美解决。燃鹅,在Django中此路不通。因为Django的视图函数是接收到request
请求后再进行后续的操作,我们的base.html
是在模板中直接继承的,根本没有发送额外的请求,使用就不能单独的进行逻辑处理。Veto!!
|
三号坑,重写render方法
终于百度到一条可行的解决方法,思路很清奇。重写Django框架中的render方法,让它能动态渲染base.html
。确实很牛,从根本解决了问题,强烈建议Django官方填了这个坑。但是我这儿还是不想用,因为重写render
方法之后我依然需要改动许多调用render
的地方。Veto!!!
django解决其他页面继承不了base模板的动态数据的问题
四号坑,伪造请求
前面不是提到Django需要请求才能渲染页面嘛,base.html
又不能传入请求。突然想到,我们直接伪造一个请求传进去不就好了。奇技淫巧,还是不想这么干。Veto!!!!
五号坑,引入自定义模板标签
终于,谷歌到了一个方法,引入自定义标签。简单解释一下,base.html
在是可以使用模板标签的,像{% if %}
、{% for %}
这种。Django又提供了自定义模板标签,就是说我们可以自己造个模板标签,就叫{% get_setting %}
吧,这个标签的功能就是从数据库获取博客名称
、博客关键词
(存在Setting这个数据表中)这些内容。
一切突然光明了~查了下官方文档,开始操作。
在index
这个应用中新建一个index_tags.py
文件:
|
然后在base.html
开头导入这个库:
|
然后就报错了:
|
什么鬼,照着官方文档的方法没错啊?逛了圈谷歌后才发现,原来在模板中引入自定义库前需要先到项目的setting.py
中注册这个库。Django官方文档怎么没说啊啊啊。
打开blog
项目下的setting.py
文件,改写如下几行:
|
六号坑,不存在分配标签
先说明一下,Django中有三种自定义标签,分别是:
- simple_tag (简单标签) – 单次使用只能返回一层数据。在这里就是说,不能从数据库中返回一条记录作为实例再渲染,只能分别定义N个简单标签分别渲染N条字段。
- inclusion_tag (内涵标签) – 可以在标签中传入参数,这里没用。
- assignment_tag (分配标签) – 使用标签时可以定义别名,作为一个实例,然后可以渲染这个实例的各个对象。在这里就是说可以直接定义一个分配标签,然后在模板中定义一个别名“setting”,然后用 分配渲染。
承接上文,我们注册了index_tags.py
这个库后终于可以在模板引入了。在模板中使用自定义标签{% get_setting %}
。又报错了:
|
什么鬼?找不到assignment_tag
对象???还是照着官方的用法没错啊,网上也都是这个干的。走投无路,忍无可忍,翻了一下Django框架的源码。发现……Django2
已经启用了assignment_tag
和inclusion_tag
标签,所有标签的功能都集中在了simple_tag
上。想想也是啊,一个标签可以解决的事情,干嘛撑得用三个。Django官方改进功能值得表扬,但是你TM能不能顺便更新一下文档,您的最新文档不是误导我们嘛!差点气晕!Veto!!!!!!
填完各种天坑之后,终于完美解决了这个问题,头发掉了一大把,还是很开心。呵呵……呵呵呵……真是醉了……承接上文[填坑]
- 本文作者:zhaoo
- 本文链接:https://www.izhaoo.com/2018/09/01/django-template-tags/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!
