首页 > 代码库 > Mastering Django笔记 ch3 Templates
Mastering Django笔记 ch3 Templates
Django的模板
前后端分离:数据展现和业务逻辑的分离,设计页面和代码是两种分工
django模板:
- {{ var }} 变量
- {% tag %} 模板tag
- {{ var | filter }} filter
django有自己的模板引擎,也可以通过配置使用其他的第三方引擎,django1.8引入了对Jinja2的支持。
作者建议,没有特殊原因还是使用django的模板DTL(Django Template Language)
django模板直接在python code中的使用:
>>> from django import template >>> t = template.Template(‘My name is {{ name }}.‘) >>> c = template.Context({‘name‘: ‘Nige‘}) >>> print (t.render(c)) My name is Nige. >>> c = template.Context({‘name‘: ‘Barry‘}) >>> print (t.render(c)) My name is Barry.
>>> from django.template import Context, Template >>> t = Template(‘My name is {{ name }}.‘) >>> c = Context({‘name‘: ‘Stephane‘}) >>> t.render(c) ‘My name is Stephane.‘
注:`python manage.py shell`和python shell的区别是,前者会告诉django使用什么配置(DJANGO_SETTINGS_MODULE),manage.py 中定义了改环境变量。
注:t.render()默认返回字符串的表示,会将‘\n‘使用换行的字符表示打印出来
(作者)django的模板解析速度相当快,大多数解析都是通过匹配单个正则表达式完成,和基于xml的模板引擎(xml解析器)相比,速度要快上几个数量级。
Context variable lookup
DTL的context按照下面顺序查找 ‘.‘
- 字典获取value:obj.key
- 对象属性
- 对象方法,只能调用没有参数的方法
- 列表下标索引(只能使用非负整数):items.1
方法调用时,如果发生异常,除非异常有slient_variable_failure并且值为True的属性,该异常会传递出去:
>>>t = Template("My name is {{ person.first_name }}.") >>> class PersonClass3: ... def first_name(self): ... raise AssertionError("foo") >>> p = PersonClass3() >>> t.render(Context({"person": p})) Traceback (most recent call last): ... AssertionError: foo >>> class SilentAssertionError(Exception): ... silent_variable_failure = True >>> class PersonClass4: ... def first_name(self): ... raise SilentAssertionError >>> p = PersonClass4() >>> t.render(Context({"person": p})) ‘My name is .‘
在t.render()时会调用方法,有些方法有副作用,例如{{ account.delete }},当模板进行渲染时,account对象调用该方法。为了避免这种情况,可以设置方法的alters_data属性,alters_data为True时,模板不会执行该方法,并将改变量替换为string_if_invalid:
def delete(self): # Delete the account delete.alters_data = http://www.mamicode.com/True
注:django的model对象动态生成的delete()和save(),会自动设置alters_data=http://www.mamicode.com/true
如果一个变量不存在,模板系统会将引擎的string_if_invalid配置项替换该变量(默认是空字符串)
DTL自带/内建的tags:
- if/else/elif/endif,不支持括号来进行优先级定义(使用嵌套if来解决)
- for/in/reversed/endfor, 支持形似 {% for k, v in data.items %} 的语法,空检查:empty,forloop变量:forloop.counter(从1开始),forloop.counter0(从0开始),forloop.revcounter, forloop.revcounter0, forloop.first, forloop.last, forloop.parentloop指向上层循环,forloop会自动屏蔽上层循环的变量
- ifequal/ifnotequal,只支持模板变量,字符串,数字,和==/!=同义
- 注释:单行 {# This is a comment. #} ,多行 {% comment %}, 不能嵌套,渲染结果不会包含注释
- 过滤器:管道字符 ‘|‘,部分支持参数,例如 {{ bio | truncatewords:"30" }} 显示前30个词, lower, upper, addslashes, date kength
DTL 设计哲学
(作者)最重要的是要知道,DTL是有意做出的一些限制的
Django诞生于大容量,易变的在线新闻室的环境下,它的设计们对DTL有一套准则/哲学:
- 分离逻辑和表现:DTL是一个控制逻辑和表现的工具,仅此而已
- 摒弃冗余:通过继承去掉冗余的代码
- 从HTML中解耦:应该支持多种输出,不只是html
- XML is bad:xml容易写错,解析性能差
- 设计师能胜任:通过HTML容易开发,但不支持像在Dreamweaver中编辑一样(导致复杂)
- 显式处理白空格:任意不在标签内的白空格都应该进行显示
- 不发明新的语言:不要求设计师会python
- 保证安全和可靠:不允许引入执行类似删除数据库这样的操作
- 可扩展
将模板和views分离:1. 不用handle模板读取的IOError 2. 模板路径可以复用 3. 不用重复写文件打开关闭的逻辑
模板加载
TEMPLATES 配置项:
- 模板BACKEND类名,内置的有两种:‘django.template.backends.django.DjangoTemplates‘ 或者 ‘django.template.backends.jinja2.Jinja2‘
- DIRS是一个list,定义了模板文件的目录
- APP_DIRS:是否扫描每个INSTALLED_APPS中"templates"目录
- OPTIONS (具体的设置)
get_template会首先找当前app下面的templates目录,如果没找到才去DIRS里面找,如果还没找到会抛出TemplateDoesNotExist 异常
render()
from django.shortcuts import render import datetime def current_datetime(request): now = datetime.datetime.now() return render(request, ‘current_datetime.html‘, {‘current_date‘: now})
include: 模板名字既可以是string也可以是变量
注:如果include的模板不存在时,DEBUG打开的情况下会抛出TemplateDoesNotExist异常,DEBUG关闭时会静默并在include那里不显示任何东西
注:在include之前,模板已经完成了渲染
模板继承
extends/block: django的模板继承允许创建一个骨架,然后个性化地塞东西。
继承链上每一层都能访问Context
block.super: 获取父级模板的block
Mastering Django笔记 ch3 Templates