首页 > 代码库 > Mastering Django笔记 ch3 Templates

Mastering Django笔记 ch3 Templates

Django的模板

前后端分离:数据展现和业务逻辑的分离,设计页面和代码是两种分工

django模板:

  1. {{ var }}  变量
  2. {% tag %} 模板tag
  3. {{ 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按照下面顺序查找 ‘.‘

  1. 字典获取value:obj.key
  2. 对象属性
  3. 对象方法,只能调用没有参数的方法
  4. 列表下标索引(只能使用非负整数):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:

  1. if/else/elif/endif,不支持括号来进行优先级定义(使用嵌套if来解决)
  2. 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会自动屏蔽上层循环的变量
  3. ifequal/ifnotequal,只支持模板变量,字符串,数字,和==/!=同义
  4. 注释:单行 {# This is a comment. #} ,多行 {% comment %}, 不能嵌套,渲染结果不会包含注释
  5. 过滤器:管道字符 ‘|‘,部分支持参数,例如 {{ bio | truncatewords:"30" }} 显示前30个词, lower, upper, addslashes, date kength

DTL 设计哲学

(作者)最重要的是要知道,DTL是有意做出的一些限制的

Django诞生于大容量,易变的在线新闻室的环境下,它的设计们对DTL有一套准则/哲学:

  1. 分离逻辑和表现:DTL是一个控制逻辑和表现的工具,仅此而已
  2. 摒弃冗余:通过继承去掉冗余的代码
  3. 从HTML中解耦:应该支持多种输出,不只是html
  4. XML is bad:xml容易写错,解析性能差
  5. 设计师能胜任:通过HTML容易开发,但不支持像在Dreamweaver中编辑一样(导致复杂)
  6. 显式处理白空格:任意不在标签内的白空格都应该进行显示
  7. 不发明新的语言:不要求设计师会python
  8. 保证安全和可靠:不允许引入执行类似删除数据库这样的操作
  9. 可扩展

 

将模板和views分离:1. 不用handle模板读取的IOError 2. 模板路径可以复用 3. 不用重复写文件打开关闭的逻辑

 

模板加载

TEMPLATES 配置项:

  1. 模板BACKEND类名,内置的有两种:‘django.template.backends.django.DjangoTemplates‘ 或者 ‘django.template.backends.jinja2.Jinja2‘
  2. DIRS是一个list,定义了模板文件的目录
  3. APP_DIRS:是否扫描每个INSTALLED_APPS中"templates"目录
  4. 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