Django模板系统

1,用{{}}包围的是变量,如{{person_name}},

2,用{%%}包围的是块标签,如{%if ordered_warranty%}

块标签的含义很丰富,它告诉模板系统做一些事情

在这个例子模板中包含两个块标签:for标签表现为一个简单的循环结构,让你按顺序遍历每条数据

if标签则表现为逻辑的if语句

在这里,上面的标签检查ordered_warranty变量的值是否为True

如果是True,模板系统会显示{%if ordered_warranty%}和{%endif%}之间的内容

否则,模板系统不会显示这些内容

模板系统也支持{%else%}等其它逻辑语句

3,上面还有一个过滤器的例子,过滤器是改变变量显示的方式

上面的例子中{{ship_date|date:"F j, Y"}}把ship_date变量传递给过滤器

并给date过滤器传递了一个参数“F j, Y”,date过滤器以给定参数的形式格式化日期

类似于Unix,过滤器使用管道字符“|”

Django模板支持多种内建的块标签,并且你可以写你自己的标签

网站模板的设计,一般的,我们做网站有一些通用的部分,比如 导航,底部,访问统计代码等。合理的规划模板往往会减少工作量,同时也使得罗乱、难以阅读的静态页面布局变得优雅。

假设,我们的网站主页面除了正文是由导航条,低栏,统计栏构成。也就是nav.html,bottom.html,tongji.html。

在构建页面的时候,可以写一个base.html来包含(include)这些通用文件,如下:

{% block title %}默认标题{% endblock %}


{% include 'nav.html' %}

{% block content %}

    

这里是默认内容,所有继承自这个模板的,如果不覆盖就显示这里的默认内容。

{% endblock %}

{% include 'bottom.html' %}

{% include 'tongji.html' %}

在这里,所有的include都是引入通用文件,而block都是定义默认模块,其他继承base.html的页面,都可以在自己的页面中重新定义这些模块,达到覆盖替换的作用。

比如我们设计一个主页面index.html,继承自base.html,同时替换base.html中的title和content两个模块。以下是index.html文件的内容:

{% extends 'base.html' %}

{% block title %}欢迎光临首页{% endblock %}

{% block content %}

{% include 'ad.html' %}

这里是首页,欢迎光临

{% endblock %}

运行这个页面,你就会发现,原有的base.html中的模块被替换掉了。

注意 {%block %}中的标签是可以自定义的,不一定要content,title,但是要简单明了

if/else

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值

系统则会显示{% if %}和{% endif %}间的所有内容:

{% if today_is_weekend %}  

    

Welcome to the weekend!

  

{%else %}    

Get back to work.

{% endif %}  

{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:

{% if athlete_list and coach_list %}  

    Both athletes and coaches are available.  

{% endif %}  

{%if not athlete_list %}  

    There are no athletes.  

{% endif %}  

{%if athlete_list or coach_list %}  

    There are some athletes or some coaches.  

{% endif %}  

{%if not athlete_list or coach_list %}  

    There are no athletes or there are some coaches.  

{% endif %}  

{%if athlete_list and not coach_list %}  

    There are some athletes and absolutely no coaches.  

{% endif %}  

{% if %}标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:

{% if athlete_list and coach_list or cheerleader_list %}  

如果你想结合and和or来做高级逻辑,只需使用嵌套的{% if %}标签即可:

{% if athlete_list %}  

{%if coach_list or cheerleader_list %}  

        We have athletes, and either coaches or cheerleaders!  

    {% endif %}  

{% endif %}  

多次使用同一个逻辑符号是合法的:

{% if athlete_list or coach_list or parent_list or teacher_list %}  

没有{% elif %}标签,使用嵌套的{% if %}标签可以做到同样的事情:

{% if athlete_list %}  

    

Here are the athletes: {{ athlete_list }}.

  

{%else %}  

    

No athletes are available.

  

{%if coach_list %}  

        

Here are the coaches: {{ coach_list }}.

  

    {% endif %}  

{% endif %}  

确认使用{% endif %}来关闭{% if %}标签,否则Django触发TemplateSyntaxError

for

{% for %}标签允许你按顺序遍历一个序列中的各个元素

Python的for语句语法为for X in Y,X是用来遍历Y的变量

每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

例如,显示给定athlete_list变量来显示athlete列表

      

{%for athlete in athlete_list %}  

    

  • {{ athlete.name }}
  •   

    {% endfor %}  


    在标签里添加reversed来反序循环列表:

    {% for athlete in athlete_list reversed %}  

    ...  

    {% endfor %}  

    {%for %}标签可以嵌套:  

    {%for country in countries %}  

        

    {{ country.name }}

      

        

        

    {%for city in country.city_list %}  

            

  • {{ city }}
  •   

        {% endfor %}  


    {% endfor %}  

    系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值

    类似的,系统也不支持continue语句,本章后面的“哲学和限制”会解释设计的原则

    {% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息

    1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:

    {% for item in todo_list %}  

        

    {{ forloop.counter }}: {{ item }}

      

    {% endfor %}  

    2,forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0

    3,forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1

    4,forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0

    5,forloop.first当第一次循环时值为True,在特别情况下很有用:

    {% for object in objects %}  

    {%if forloop.first %}{% else %}

  • {% endif %}  
  •     {{ object }}  


    {% endfor %}  

    6,forloop.last当最后一次循环时值为True

    {% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}  

    7,forloop.parentloop在嵌套循环中表示父循环的forloop:

    {% for country in countries %}  

          

    {%for city in country.city_list %}  


                Country #{{ forloop.parentloop.counter }}   

                City #{{ forloop.counter }}  

                {{ city }}  


        {% endfor %}  


    {% endfor %}  

    富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了

    如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它

    Django会在for标签的块中覆盖你定义的forloop变量的值

    在其他非循环的地方,你的forloop变量仍然可用

    我们建议模板变量不要使用forloop,如果你需要这样做来访问你自定义的forloop,你可以使用forloop.parentloop

    ifequal/ifnotequal

    Django模板系统并不是一个严格意义上的编程语言,所以它并不允许我们执行Python语句

    (我们会在‘哲学和限制‘一节详细讨论)。

    然而在模板语言里比较两个值并且在他们一致的时候显示一些内容,确实是一个在常见不过的需求了——所以Django提供了ifequal标签。

    {% ifequal %}比较两个值,如果相等,则显示{% ifequal %}和{% endifequal %}之间的所有内容:

    {% ifequal user currentuser %}  

        

    Welcome!

      

    {% endifequal %}  

    参数可以是硬编码的string,单引号和双引号均可,下面的代码是合法的:

    {% ifequal section 'sitenews' %}  

        

    Site News

      

    {% endifequal %}  

    {% ifequal section"community" %}  

        

    Community

      

    {% endifequal %}  

    和{% if %}一样,{% ifequal %}标签支持{% else %}

    {% ifequal section 'sitenews' %}  

        

    Site News

      

    {%else %}  

        

    No News Here

      

    {% endifequal %}  

    其它的模板变量,strings,integers和小数都可以作为{% ifequal %}的参数:

    {% ifequal variable 1 %}  

    {% ifequal variable1.23 %}  

    {% ifequal variable'foo' %}  

    {% ifequal variable"foo" %}  

    其它的Python类型,如字典、列表或booleans不能硬编码在{% ifequal %}里面,下面是不合法的:

    {% ifequal variable True %}  

    {% ifequal variable [1, 2, 3,]%}  

    {% ifequal variable {'key': 'value'} %  

    如果你需要测试某个变量是true或false,用{% if %}即可

    注释

    和HTML或编程语言如Python一样,Django模板语言允许注释{# #},如:

    {# This is a comment #}  

    模板渲染时注释不会输出,一个注释不能分成多行

    下面的模板渲染时会和模板中的内容一样,注释标签不会解析成注释

    This is a {# comment goes here

    and spans another line #}

    test.

    过滤器

    本章前面提到,模板过滤器是变量显示前转换它们的值的方式,看起来像下面这样:

    {{ name|lower }}  

    这将显示通过lower过滤器过滤后{{ name }}变量的值,它将文本转换成小写

    使用(|)管道来申请一个过滤器

    过滤器可以串成链,即一个过滤器的结果可以传向下一个

    下面是escape文本内容然后把换行转换成p标签的习惯用法:

    {{ my_text|escape|linebreaks }}  

    有些过滤器需要参数,需要参数的过滤器的样子:

    {{ bio|truncatewords:"30" }}  

    这将显示bio标量的前30个字,过滤器参数一直使用双引号

    下面是一些最重要的过滤器:

    1,addslashed,在任何后斜线,单引号,双引号前添加一个后斜线

    当你把一些文本输出到一个JavaScript字符串时这会十分有用

    2,date,根据一个格式化string参数来格式化date或datetime对象,例如:

    {{ pub_date|date:"F j, Y" }}  

    格式化string会在附录6定义

    3,escape,避免给定的string里出现and符,引号,尖括号

    当你处理用户提交的数据和确认合法的XML和XHTML数据时这将很有用

    escape将作如下的一些转换:

    Converts & to &  

    Converts < to &lt;  

    Converts > to &gt;  

    Converts "(双引号) to &quot;  

    Converts '(单引号) to &#39;  

    4,length,返回值的长度,你可以在一个list或string上做此操作

    或者在任何知道怎样决定自己的长度的Python对象上做此操作(即有一个__len__()方法的对象)

    哲学和限制

    现在我们对于Django地模板系统有了一个感性的认识,下面我们将指出一些有意为之的限制和它工作的哲学

    不像其他Web程序组件,程序员对模板系统的意见非常不一致

    一个很有意思的事实:Python至少拥有数十个——如果没有上百个——的开源模板语言实现,而且看来每一个都是因为其创造者认为现有的模板不能满足他们的要求。

    (事实上,据说写一个自己的模板系统是已经成了Python开发者必经的仪式了。如果你还没有写过自己的模板系统,试试看吧,真是很有意思。)

    所以,Django的第一个哲学就是Django不强求你使用它的模板语言

    Django的目标是提供一个full-stack框架,提供所有必须的web开发模块进行高效开发

    很多时候,使用Django的模板系统很方便,但不强求你使用它

    下面的“在视图中使用模板”一节我们会看到在Django中使用另一套模板语言,它同样简单易用

    但我们仍强烈需要Django的模板语言的工作方式,模板系统深植于World Online和Django发明者的

    Web开发方式中,下面是其中一些哲学:

    1,业务逻辑应该和呈现逻辑分离

    模板系统应该只负责控制显示和显示相关的逻辑我们视模板为一种控制显示和显示相关逻辑的工具,仅此而已。模板系统的功能就止于此。

    基于这个原因,Django模板无法直接调用Python代码。在Django模板里,所有的程序设计活动都止于对标签的使用。

    虽然你可以自定义模板标签来做任意的事情,但Django自己的模板标签不允许执行Python代码。

    2,语法应该和HTML/XML解耦

    Django的模板系统采用非HTML格式,如普通的文本,有些其它的模板语言是基于XML的

    XML的格式容易输错,并且XML的模板解析速度也容易变得很慢而难以接受

    3,页面设计者被假定为熟悉HTML代码

    Django模板系统没有设计成可以在Dreamweaver等WYSISYG编辑器中显示良好

    这类编辑器有很多限制,Django希望模板作者直接编辑HTML时感到舒适

    4,页面设计者被假定为不是Python程序员

    模板系统的作者意识到大部分Web页面的模板是页面设计者写的而不是Python程序员写的

    他们不具备Python知识,但Django也允许模板用Python来写,它提供了一种直接编写Python代码

    来扩展模板系统的方法(第10章会介绍更多)

    5,目标不是发明一种编程语言

    目标只是提供足够的编程功能,如分支和循环等决定呈现相关的逻辑用

    由于上述的设计哲学,Django模板系统产生如下限制:

    1,模板不能设置和改变变量的值

    可以通过自定义模板标签来达到这个目标(I参看第10章),但是内置Django模板标签不允许这样做

    2,模板不能调用原生Python代码

    但是也可以通过自定义标签来做这件事情

    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 204,530评论 6 478
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 86,403评论 2 381
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 151,120评论 0 337
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 54,770评论 1 277
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 63,758评论 5 367
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 48,649评论 1 281
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 38,021评论 3 398
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 36,675评论 0 258
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 40,931评论 1 299
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 35,659评论 2 321
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 37,751评论 1 330
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 33,410评论 4 321
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 39,004评论 3 307
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 29,969评论 0 19
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 31,203评论 1 260
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 45,042评论 2 350
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 42,493评论 2 343

    推荐阅读更多精彩内容