天天看点

初识Django(六):模版语言

其实我接触过的web框架也就Java下的jsp和Python下的web.py和django、flask,但是他们都有类似模版语言的存在,有的是像Django一样专门的创造,有的是简单的在html文档里嵌入编程语句。但是毋庸置疑,这些“模版语言”是让html文件变得动态的根源。

模版语言定义(Django Template Language, DTL)

Django的模版语言十分简明,很容易就能学会。我们用几个判断句来给模版语言定义。

-1 所有使用了模版语言的html文件被我们称为模版。

-2 在模版语言中,{% 语句 %}、{{ 输出 }}、{# 注释 #}。也就是说前者括号内的内容会被django执行,后者直接被运算后写在文件的相应位置上。

-3 在模版语言中,我们的变量可以使用|(过滤器)和.运算符,我们的语句可以用来载入内容或使用for/if/block/extends/url等标签。不能直接运行python语言,这点要谨记。

{{ 输出 }}

1 View与Template的交互

模版由视图渲染并传给客户端,使用render函数。当模版中需要数据时,我们向render函数传入同键名的字典。render函数的介绍在上一部分。

2 .运算符

DTL中的点运算符按照字典->对象->列表/元组查询,当以上查询都不成立的时候返回空字符串。也就是说,如果你在前端传入了一个数组a=[1,2,…],前端模版内你对其的访问应为a.1、a.2…

例1 view传值:

示例项目根路径下urls.py里urlpatterns添加:

path("thirdurl",views.third)

子app helloworld下views.py:

def third(request):

if(request.method=="GET"):

dictionary={"key1":"1","key2":[1,2,3,4],"key3":{"a":"a","b":"b"}}

return render(request,"我的html.html",dictionary)

子app helloworld下文件夹templates下我的html.html:

<!doctype html>

<html>

<head></head>

<body>

{{key1}}

{{key2.0}}

{{key3.a}}

</body>

</html>

项目下打开命令行runserver在127.0.0.1:8000下运行django,输入127.0.0.1:8000/thirdurl,可以看到返回了1 1 a。

3 |运算符与过滤器

过滤器可以被视为专门用来处理模版数据的python函数,在模版中,我们通过|运算符使用过滤器。Django内置了很多过滤器,这些可以在网上搜到,我们也可以自己制作过滤器。

-过滤器在使用之前需要使用{% load 过滤器文件名 %}导入。

-过滤器文件默认放在app目录下templatetags文件夹下。

-过滤器文件中定义的函数即是过滤器,函数前要加上@register.filter(name="过滤器在模版中的名字"),整个文件前要加上两行:from django import template register=template.Library()。

例2 使用django自带的过滤器:

示例项目根路径下urls.py里urlpatterns添加:

path("fourthurl",views.fourth)

子app helloworld下views.py:

def fourth(request):

if(request.method=="GET"):

dictionary={"key1":"1"}

return render(request,"我的html.html",dictionary)

子app helloworld下文件夹templates下我的html.html:

<!doctype html>

<html>

<head></head>

<body>

{{key1.1|default:"不存在"}}

</body>

</html>

过滤器default为django自带的过滤器,功能为在返回空串时替代为后面的字符串。这个过滤器不需要导入(但是不是所有自带的过滤器都不要)。项目下打开命令行runserver在127.0.0.1:8000下运行django,输入127.0.0.1:8000/thirdurl,可以看到返回了“不存在”,因为key1.1找不到值。

例3 一个小例子,自建过滤器:

子app helloworld下文件夹templatetags文件夹下建立block1.py:

from django import template

register=template.Library()

@register.filter(name="_reverse")#这个过滤器翻转list

def _reverse(arg):

return reversed(arg)

在模版文件中这么引用:

<!doctype html>

<html>

<head></head>

<body>

{% load block1 %}

{{arg1|_reverse}}

</body>

</html>

{% 语句 %}

1 load语句

load语句用来载入自定义标签或过滤器文件,比如大名鼎鼎的{% load static %}。

# load static与 static ‘’

{% load static %}载入了static标签,{% static ‘文件路径’ %}用于加载静态文件。

很多人把static标签说的玄之又玄,其实不然。在没有额外设置的情况下,django会去app目录下的static目录下寻找static引号里字符串为路径的文件。(关于这些静态文件存放请参考我之前讲的模版文件的存放,请仔细思考django寻找文件的顺序和文件的储存顺序,如果你直接随意存储文件,当其重名时django只会返回第一个查找的,这里没有对于app的就近原则)

-如果想要修改static目录的名字,请修改settings.py文件下的STATIC_URL。(根据url的解析规则你应该能意会这个变量定义了什么)

-如果你的static不想放在app目录下,可以在settings.py文件下添加STATICFILES_DIRS变量,将其值设为你设定的static文件夹,例如STATICFILES_DIRS= (os.path.join(BASE_DIR, "static"),),则静态文件夹为项目目录下的static文件夹。

2 for语句和if语句

DTL中的for语句和if语句的使用与python中相同,但是书写方式有所不同。

{% for 表达式 %}内容{% endfor %} for语句

{% if 表达式 %}内容{% endif %} if语句

你可能注意到了两个语句之间我写的是内容而不是语句,事实上里面也可以写html标签。不要想当然。

3 block语句

block语句扩住的内容可以被覆写。我们通过引用模版并覆写其中的block完成模版代码的重用,如果不覆写块中的内容就是父模版中块的内容。(可以想象一个父类和重写父类方法的子类)这个特性可以很好的用于节省模版的编写时间,也可以让模版层次分明。

{% block 名称 %}内容{% endblock 名称 %} block语句

{% extends ‘模版文件名称’ %} 引用模版文件

例4 覆写block及引用static

项目app helloworld目录下模版文件夹下新建 父模版.html:

<!doctype html>

<html>

<head></head>

<body>

{% block myblock1 %}

<p>父内容</p>

{% endblock myblock1 %}

</body>

</html>

同目录新建 子模版.html:

{% extends ‘父模版.html’ %}

{% block myblock1 %}

<p>子内容</p>

{% endblock myblock1 %}

很明显,如果你的项目渲染了子模版,那么会出现“子内容”。

{# 注释 #}

关于这个注释只有一个需要注意的。Html文件的注释还会出现在文件内,只不过不被呈现出来,而DTL的注释在渲染模版的时候就会被剔除。

关于DTL的一些思考

相比于直接在模版文件中嵌入python语句,DTL显得更加高明。因为它不但简洁,而且从框架编写者的方面就严格遵循了MTV模式,不需要使用框架者特意去注意这些。这就像“带上脚镣的舞蹈”,是有限制的自由,但是也更美。

Tips:本文里涉及DTL的语句和标签是等价的。