django 中模板语言的各种用法

模板

1、视图中使用模板

  模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户

1.普通方法:HTML被直接硬编码在 Python 代码

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)
View Code

  尽管这种技术便于解释视图是如何工作的,但直接将HTML硬编码到你的视图里却并不是一个好主意,我们应该将页面的设计和Python的代码分离开会更干净简洁更容易维护。这时,我们可以使用 Django的 模板系统 (Template System)来实现这种模式

2.Django 模版基本语法

1、创建模板:
一旦你创建一个 Template 对象,你可以用 context 来传递数据给它。 一个context是一系列变量和它们值的集合
from django import template
t = template.Template('My name is {{ name }}.')#创建Template 对象
c = template.Context({'name': 'SunshineBoy'}) #创建一个 Context 对象
print(t.render(c))
>>>u'My name is SunshineBoy'
#另外同一模板,可以有多个上下文,即可以同一模板渲染多个context 

#context在Django里表现为 Context 类,在 django.template 模块里。 她的构造函数带有一个可选的参数: 一个字典映射变量和它们的值。 调用 Template 对象 的 render() 方法并传递context来填充模板

ps:我们可以使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会更为高效

注意:t.render(c)返回的值是一个Unicode对象,不是普通的Python字符串。 你可以通过字符串前的u来区分。 在框架中,Django会一直使用Unicode对象而不是普通的字符串

Template加载

通过settings去加载模板
import datetime
from django import template
import DjangoDemo.settings
 
now = datetime.datetime.now()
fp = open(settings.BASE_DIR+'/templates/Home/Index.html')
t = template.Template(fp.read())
fp.close()
html = t.render(template.Context({'current_date': now}))
return HttpResponse(html)
View Code
一般来说,你在你的文件系统中存入模板,但你也可以使用自定义的template加载器去从其它地方加载你的模板。
Django有两种方式去加载你的模板:
    1. django.template.loader.get_template(template_name):get_template通过模板名参数,返回一个模板对象,如果模板不存在,报错TemplateDoesNotExist
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
 
def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)
View Code
    2. django.template.loader.select_template(template_name_list):参数为模板名的列表,返回第一个
存在的模板,如果列表中所有模板都不存在,就报错TemplateDoesNotExist
 
    以上函数都默认在settings.py中TEMPLATE_DIRS属性下添加的路径下查找,不过,在内部机制上,这些函数也可以指定不同的加载器来完成这些任务。
 
    加载器的设置在settings.py中的TEMPLATE_LOADERS属性中,它是一个字符串元组类型,每一个字符串代表一个loader类型。有些被默认开启,有些是默认关闭的。可以一起使用,直到找到模板为止。
 
TEMPLATE_LOADERS = (
    #'django_mobile.loader.Loader',
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    #'django.template.loaders.eggs.Loader',
)
    1. django.template.loaders.filesystem.Loader:默认开启,从TEMPLATE_DIRS路径中加载模板
    2. django.template.loaders.app_directories.Loader:默认开启,这个装载器会在每一个INSTALLED_APPS,注册的app目录下寻找templates子目录,如果有的话,就会在子目录中加载模板。这样就可以把模板和app放在一起,方便重用。这个装载器会有一些优化,在第一次导入的时候,会缓存包含templates子目录的app
包的列表。
    3. django.template.loaders.eggs.Loader:默认关闭,从egg文件中加载模板,egg文件类似jar包,python中打包发布代码的一种方式。和app_directories Loader类似也是从app子目录template中加载egg文件

  以上这些均是底层如何载入一个模板文件,然后用 Context渲染它,最后返回这个处理好的HttpResponse对象给用户。 我们已经优化了方案,使用 get_template() 方法代替繁杂的用代码来处理模板及其路径的工作。 但这仍然需要一定量的时间来敲出这些简化的代码。 这是一个普遍存在的重复苦力劳动。

  Django为此提供了一个捷径,让你一次性地载入某个模板文件,渲染它,然后将此作为 HttpResponse返回。

该捷径就是位于 django.shortcuts 模块中名为 render_to_response() 的函数

from django.shortcuts import render_to_response
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

 

2、深度变量的查找

  前面,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。

  在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

如:假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点(.)

from django.template import Template, Context
person = {'name': 'Lily', 'age': '22'}
t = Template('{{ person.name }} is {{ person.age }} years old.')
c = Context({'person': person})
print(t.render(c))

>>>u'Lily is 22 years old.'

同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有 year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性:

>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1995, 5, 20)
>>> d.year
1993
>>> d.month
5
>>> d.day
2
>>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
>>> c = Context({'date': d})
>>> t.render(c)

u'The month is 5 and the year is 1995.'

同样,我们自定义类的实例对象也可以通过(.)来访问其实例属性

>>> from django.template import Template, Context
>>> class Person(object):
...     def __init__(self, first_name, last_name):
...         self.first_name, self.last_name = first_name, last_name
>>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.')
>>> c = Context({'person': Person('John', 'Smith')})
>>> t.render(c)
u'Hello, John Smith.'

点语法也可以用来引用对象的* 方法*。 例如,每个 Python 字符串都有 upper() 和 isdigit() 方法

>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
u'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
u'123 -- 123 -- True'

ps:注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的方法

最后,句点也可用于访问列表索引,例如

>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Context({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
u'Item 2 is carrots.'

3、模版语言

模板中也有自己的语言,该语言可以实现数据展示#引用变量

{{ item }}

#引用标签(tag)
{% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}

  forloop.counter  #一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1,forloop.counter0 它是从0计数的
  forloop.first  #是否是循环的第一个 ,布尔值
  forloop.last  #是否是循环的最后一个 ,布尔值

{% if ordered_warranty %}  {% else %} {% endif %}

#继承
母板:{% block title %}{% endblock %}   
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}

#过滤器:
{{ item.event_start|date:"Y-m-d H:i:s"}} #时间格式化
{{ bio|truncatewords:"n" }}  #对字符串进行截段,,取这个模板变量的前 N 个字符,只能用于英文
{{ bio|slice:"n" }}   #取变量前 N 个字符,可用于中文 
{{ my_list|first|upper }} {{ name|lower }}
{{ value|default:"nothing" }}  #如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值
# Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义 {{ value|safe}} #通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义

 

 

4、 用simple_tag 来自定义模板方法

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py

#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
   
register = template.Library() #只能是register不能改为其它
   
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
   
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)    #使用方法函数mark_safe ,使用mark_safe函数标记后,django将不再对该函数的内容进行转义.因为django默认会自动转义模板中的内容,把标签转换为相应的HTML实体。这样可以防止后端为数据库的网站被恶意脚本攻击

c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

{% load xx %}

d、使用simple_tag

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配置当前app,不然django无法找到自定义的simple_tag

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
)

 

posted @ 2017-05-28 20:41  似是故人来~  阅读(1939)  评论(0编辑  收藏  举报