模板的应用原理、过程

以mysite项目为例:

当一个url开始匹配开始时,先去mysite/mysite/urls.py 里匹配,然后里面会具体匹配到哪个应用,调用相应应用下的urls.py,(例如这里是polls)-> mysite/mysite/polls/urls.py 里面匹配到相应的url后,会调用polls应用下views.py里相应的函数 -> mysite/mysite/polls/views.py 最后使用render或render_to_response输出相应的模板 ->  mysite/mysite/polls/templates/polls/template.html 

如果这个模板还通过include引用了其他页面,或继承于其他模板页面,会继续加载相应的页面或模板

 

模板的配置方法

先在项目/setting.py下配置添加模板路径

setting.py内TEMPLATES 设置中添加一个DIRS 选项 :

        'DIRS': [os.path.join(BASE_DIR, 'templates')],

        其中BASE_DIR =os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

然后再在相应应用下面建立模板目录,放置模板文件,最终结构是templates/应用名称(例如polls)/模板文件(index.html等) ,使用时系统会自动查找templates目录,注意是templates目录,要自行加上plls路径,不然会找不到文件

 

模板中的注释

l  单行:{# This is acomment #}

l  多行:要使用标签了

{% comment %}

This is a

multi‐line comment.

{% endcomment %}

 

过滤器

模板过滤器是在变量被显示前修改它的值的一个简单方法。过滤器使用管道字符。

例1:小写转换

{{ name|lower }}

显示的内容是变量 ` name ` 被过滤器 lower 处理后的结果,它功能是转换文本为小写。

例2:日期格式化显示

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

例3:

{{ bio|truncatewords:"30" }}

这个将显示变量 bio 的前30个词。

 

基本的模板标签

1、include标签

内建模板标签: {% include %} 。该标签允许在

(模板中)包含其它的模板的内容。标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引

号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重

复。

例:

{% include ‘polls/foot.html’%}

 

2、if/else标签

标签检查(evaluate)一个变量,如果这个变量为真(即,变量存在,非空,不是布尔值假),系统会

显示在 {% if %} 和 {% endif %} 之间的任何内容

例:

{% if today_is_weekend %}

Welcome to the weekend!

{% endif %}

 

{% else %} 标签是可选的:

 

{% if today_is_weekend %}

Welcome to the weekend!

{% else %}

Get back to work.

{% endif %}

注意:

1、在Python和Django模板系统中,以下这些对象相当于布尔值的False,其余的都是True

l  空列表([] )

l  空元组(() )

l  空字典({} )

l  空字符串('' )

l  零值(0 )

l  特殊对象None

l  对象False(很明显)

2、{% if %} 标签不允许在同一个标签中同时使用 and 和 or ,因为逻辑上可能模糊的

       例:{% ifathlete_list and coach_list or cheerleader_list %}  这是错误的

3、系统不支持用圆括号来组合比较操作。如果你确实需要用到圆括号来组合表达你的逻辑式,考虑将它移到模板

之外处理,然后以模板变量的形式传入结果吧。或者,仅仅用嵌套的{% if %}标签替换吧,就像这样:

{% if athlete_list %}

       {% if coach_list orcheerleader_list %}

              We have athletes,and either coaches or cheerleaders!

{      % endif %}

{% endif %}

4、多次使用同一个逻辑操作符是没有问题的,但是我们不能把不同的操作符组合起来。例如,这是合法的:

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

5、没有 {% elif %} 标签,并且一定要用 {% endif %} 关闭每一个 {% if %} 标签。

 

3、for标签

{%for %} 允许我们在一个序列上迭代。 与Python的 for 语句的情形类似,循环语法是 for X in Y ,Y是要迭

代的序列而X是在每一个特定的循环中使用的变量名称。 每一次循环中,模板系统会渲染在 {% for%} 和

{%endfor %} 之间的所有内容。

例:

{% for athlete in athlete_list %}

      

  • `athlete`.`name `
  • {% endfor %}

     

    在执行循环之前先检测列表的大小是一个通常的做法,当列表为空时输出一些特别的提示。

    {%if athlete_list %}

           {% for athlete in athlete_list %}

                 

    ` athlete`.`name`

           {% endfor %}

    {%else %}

          

    There are no athletes. Onlycomputer programmers.

    {%endif %}

     

    for标签里有很多变量,方便我们的使用。在每个``{% for %}``循环里有一个称为`` forloop`` 的模板变量。这个变量有一些提示循环进度信息的属性。

    l  forloop.counter 总是一个表示当前循环的执行次数的整数计数器。这个计数器是从1开始的,所以在第一

    次循环时forloop.counter 将会被设置为1。

    例:结果会显示1 2 3

    y=[1,2,3]

    {% for x in y %}

    ` forloop`.`counter `

    {% endfor %}

    l  forloop.counter0 类似于 forloop.counter ,但是它是从0计数的。第一次执行循环时这个变量会被设置

    为0。

    l  forloop.revcounter 是表示循环中剩余项的整型变量。在循环初次执行时 forloop.revcounter 将被设置

    为序列中项的总数。最后一次循环执行中,这个变量将被置1。

    l  forloop.revcounter0 类似于 forloop.revcounter,但它以0做为结束索引。在第一次执行循环时,该变

    量会被置为序列的项的个数减1。

    l  forloop.first 是一个布尔值,如果该迭代是第一次执行,那么它被置为````

    l  forloop.last 是一个布尔值;在最后一次执行循环时被置为True

    l  forloop.parentloop 是一个指向当前循环的上一级循环的forloop对象的引用(在嵌套循环的情况下)。

    例:

    {% for country incountries %}

    {% for city incountry.city_list %}

    {% endfor %}

    Country #`forloop`.`parentloop`.`counter ` City #`forloop`.`counter ` ` city`

    {% endfor %}

     

    注意:

    l  Django不支持退出循环操作。 如果我们想退出循环,可以改变正在迭代的变量,让其仅仅包含需要迭代的项目。同理,Django也不支持continue语句,我们无法让当前迭代操作跳回到循环头部。

    l  forloop 变量仅仅能够在循环中使用。 在模板解析器碰到{% endfor %}标签后,forloop就不可访问了

     

    4、ifequal/ifnotequal标签

    {%ifequal %} 标签比较两个值,当他们相等时,显示在 {% ifequal %} 和 {% endifequal %} 之中所有的值。

    例:比较两个模板变量 user 和 currentuser :

    {% ifequal user currentuser %}

          

    Welcome!

    {% endifequal %}

     

    参数可以是硬编码的字符串,随便用单引号或者双引号引起来,所以下列代码都是正确的:

    {% ifequal section 'sitenews' %}

          

    SiteNews

    {% endifequal %}

     

    和 {% if %} 类似, {% ifequal %} 支持可选的 {% else%} 标签:

    {% ifequal section 'sitenews' %}

          

    Site News

    {% else %}

          

    No NewsHere

    {% endifequal %}

    注意:

    l  只有模板变量,字符串,整数和小数可以作为 {% ifequal %} 标签的参数。下面是合法参数的例子:

    {% ifequal variable 1 %}

    {% ifequal variable 1.23 %}

    {% ifequal variable 'foo' %}

    {% ifequal variable"foo" %}

    l  其他任何类型,例如Python的字典类型、列表类型、布尔类型,不能用在 {% ifequal %} 中。 下面是些错误的

    例:

    {% ifequal variable True %}

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

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

    l  如果你需要判断变量是真还是假,请使用 {% if %} 来替代 {% ifequal %}

     

    模板继承

    为了减少开发中代码的书写,除了使用{% include %}共用的代码,更好的方法就是模板继承

    模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

    使用方法:第一步是定义继承模板,一个基本的html页面,页面中{% block blockname %} 内容 {% endblock %} 里的内容就是可以重载、添加或保留的那些块。当一个页面继承了所定义的模板,它可以选择自定义{% block blockname %} {% endblock %}之间的内容,如果不去改变就会沿用原有设置

    例(在视图中使用模板):

    1、先定义一个模板base.html

    {%block title %}标题内容{% endblock %}

    {%block content %}内容

    My helpful timestamp site

    {% endblock %}

    {%block footer %}


    Thanksfor visiting my site.页脚

    {%endblock %}

     

    2、然后在extends.html页面中继承base.html

    {%extends "polls/base.html" %}        #这里的路径要注意!django只会查找每个应用的templates根目录,再下一层的目录要手动写上去

    {%block title %} dx site {% endblock %}

    {%block content %}

    dx content

    {% endblock %}

     

    3、然后在polls应用下的view.py 定义一个用于测试继承的函数

    defextends_test(request):

          returnrender_to_response('polls/extends.html')

     

    4、再在polls应用下的url.py定义一个新的url匹配规则

    #ex: /polls/extends/

           url(r'extends/$', views.extends_test,name='extends_test'),

    至此,模板的继承应用就实现了

    注意:

    l  如果在模板中使用 {%extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作

    用。

    l  {% extends %} 对所传入模板名称使用的加载方法和 get_template() 相同。 也就是说,会将模板名称被添

    加到 TEMPLATE_DIRS 设置之后。

    l  多数情况下, {%extends %} 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也

    可以是个变量。 这使得你能够实现一些很酷的动态功能

     

    其他技巧

    当我们利用render或render_to_response调用模板输出的时候,可以利用locals()传入所有的局部变量到模板里,这样就可以偷懒写一个locals()就可以了。