Thanks for ordering Super Lawn Mower from Outdoor Equipment.
It's scheduled to ship on April 2, 2009.
\n\n
Your warranty information will be included
in the packaging.
\n\n\n
Sincerely, Outdoor Equipment
"[/code]
让我们来看看都做了些什么:
1,我们import Template和Context类,它们都在django.template模块里面
2,我们把模板文本存储在raw_template变量里,我们使用"""来构建string,它可以跨越多行
3,我们创建模板对象t,并给Template类的初始化函数传递raw_template变量
4,我们从Python的标准库import datetime模块,下面会用到它
5,我们创建一个context对象c,它的初始化函数使用一个映射变量名和变量值的字典
例如我们指定person_name的值为'John Smith',product的值为'Super Lawn Mower'等等
6,最后,我们调用模板对象的render()方法,参数为context对象c
这将返回渲染后的模板,将模板中的变量值替换并计算块标签的结果
如果你刚接触Python,你可能会问为什么输出中包含了新行字符'\n'而不是换行
这是因为Python交互环境中调用t.render(c)会显示string的representation而不是string的值
如果你想看到换行而不是'\n',使用print t.render(c)即可
上面是使用Django模板系统的基础,只是创建一个模板对象和context对象然后调用render()方法
同一个模板,多个context的情况:
一旦你创建了一个模板对象,你可以渲染多个context,例如:
[code]>>> from django.template import Template, Context
>>> t = Template('Hello, {{ name }}')
>>> print t.render(Context({'name': 'John'}))
Hello, John
>>> print t.render(Context({'name': 'Julie'}))
Hello, Julie
>>> print t.render(Context({'name': 'Pat'}))
Hello, Pat[/code]
无论何时,你使用同一个模板来渲染多个context的话,创建一次Template对象然后调用render()多次会更高效
[code]# Bad
for name in ('John', 'Julie', 'Pat'):
t = Template('Hello, {{ name }}')
print t.render(Context({'name': name}))
# Good
t = Template('Hello, {{ name }}')
for name in ('John', 'Julie', 'Pat'):
print t.render(Context({'name': name}))[/code]
Django的模板解析非常快,在后台,大部分的解析通过一个单独的对正则表达式的调用来做
这与基于XML的模板引擎形成鲜明对比,XML解析器比Django的模板渲染系统慢很多
[b]Context变量查找[/b]
上面的例子中,我们给模板context传递了简单的值,大部分是string,以及一个datetime.date
尽管如此,模板系统优雅的处理更复杂的数据结构,如列表,字典和自定义对象
在Django模板系统中处理复杂数据结构的关键是使用(.)字符
使用小数点来得到字典的key,属性,对象的索引和方法
下面通过例子来解释,通过(.)访问字典的key:
[code]>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c= Context({'person': person})
>>> t.render(c)
'Sally is 43 years old.'[/code]
通过(.)来访问对象的属性:
[code]>>> from django.template import Template, Context
>>> import datetime
>>> d = datetime.date(1993, 5, 2)
>>> 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)
'The month is 5 and the year is 1993.'[/code]
下面的例子使用一个自定义类:
[code]>>> 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)
'Hello, John Smith.'[/code]
小数点也可以用来调用列表的索引:
[code]>>> from django.template import Template, Context
>>> t = Template('Item 2 is {{ items.2 }}.')
>>> c = Contexst({'items': ['apples', 'bananas', 'carrots']})
>>> t.render(c)
'Item 2 is carrots.'[/code]
负数的列表索引是不允许的,例如模板变量{{ items.-1 }}将触发TemplateSyntaxError
最后小数点还可以用来访问对象的方法,例如Python的string有upper()和isdigit()方法:
[code]>>> from django.template import Template, Context
>>> t = Template('{{ var }} -- {{var.upper }} -- {{ var.isdigit }}')
>>> t.render(Context({'var': 'hello'}))
'hello -- HELLO -- False'
>>> t.render(Context({'var': '123'}))
'123 - 123 - True'[/code]
注意,调用方法时你不能加括号,你也不能给方法传递参数
你只能调用没有参数的方法,后面我们会解释这些
总结一下,当模板系统遇到变量名里有小数点时会按以下顺序查找:
1,字典查找,如foo["bar"]
2,属性查找,如foo.bar
3,方法调用,如foo.bar()
3,列表的索引查找,如foo[bar]
小数点可以多级纵深查询,例如{{ person.name.upper }}表示字典查询person['name']然后调用upper()方法
[code]>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name.upper }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
'SALLY is 43 years old.'[/code]
[b]关于方法调用[/b]
方法调用要比其他的查询稍微复杂一点,下面是需要记住的几点:
1,在方法查询的时候,如果一个方法触发了异常,这个异常会传递从而导致渲染失
败,但是如果异常有一个值为True的silent_variable_failure属性,这个变量会渲染成空string:
[code]>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClas3:
... def first_name(self):
... raise AssertionError, "foo"
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo
>>> class SilentAssetionError(AssertionError):
... silent_variable_failure = True
>>> class PersonClass4:
... def first_name(self):
... raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
"My name is ."[/code]
2,方法调用仅仅在它没有参数时起作用,否则系统将继续查找下一个类型(列表索引查询)
3,显然一些方法有副作用,让系统访问它们是很愚蠢的,而且很可能会造成安全性问
题。
例如你有一个BankAccount对象,该对象有一个delete()方法,模板系统不应该允许做下面的事情
I will now delete this valuable data. {{ account.delete }}
为了防止这种状况,可以在方法里设置一个方法属性alters_data
如果设置了alters_data=True的话模板系统就不会执行这个方法:
[code]def delete(self):
# Delete the account
delete.alters_data = True[/code]
[b]不合法的变量怎样处理[/b]
默认情况下如果变量不存在,模板系统会把它渲染成空string,例如:
[code]>>> from django.template import Template, Context
>>> t = Template('Your name is {{ name }}.')
>>> t.render(Context())
'Your name is .'
>>> t.render(Context({'var': 'hello'}))
'Your name is .'
>>> t.render(Context({'NAME': 'hello'}))
'Your name is .'
>>> t.render(Context({'Name': 'hello'}))
'Your name is .'[/code]
系统会静悄悄地显示错误的页面,而不是产生一个异常,因为这种情况通常是人为的错误。
在现实情形下,一个web站点因为一个模板代码语法的错误而变得不可用是不可接受的。
我们可以通过设置Django配置更改Django的缺省行为,第10章扩展模板引擎会我们会讨论这个
[b]if/else[/b]
{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值
系统则会显示{% if %}和{% endif %}间的所有内容:
[code]{% if today_is_weekend %}
Welcome to the weekend!
{% else %}
Get back to work.
{% endif %}[/code]
{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,例如:
[code]{% if athlete_list and coach_list %}
Both athletes and coaches are available.
{% endif %}
{% if not athlete_list %}
There are no athletes.
{% endif %}
{% if athlete_list or coach_list %}
There are some athletes or some coaches.
{% endif %}
{% if not athlete_list or coach_list %}
There are no athletes or there are some coaches.
{% endif %}
{% if athlete_list and not coach_list %}
There are some athletes and absolutely no coaches.
{% endif %}[/code]
{% if %}标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:
[code]{% if athlete_list and coach_list or cheerleader_list %}[/code]
如果你想结合and和or来做高级逻辑,只需使用嵌套的{% if %}标签即可:
[code]{% if athlete_list %}
{% if coach_list or cheerleader_list %}
We have athletes, and either coaches or cheerleaders!
{% endif %}
{% endif %}[/code]
多次使用同一个逻辑符号是合法的:
[code]{% if athlete_list or coach_list or parent_list or teacher_list %}[/code]
没有{% elif %}标签,使用嵌套的{% if %}标签可以做到同样的事情:
[code]{% if athlete_list %}
[b]for[/b]
{% for %}标签允许你按顺序遍历一个序列中的各个元素
Python的for语句语法为for X in Y,X是用来遍历Y的变量
每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容
例如,显示给定athlete_list变量来显示athlete列表:
[code]
{% for athlete in athlete_list %}
{{ athlete.name }}
{% endfor %}
[/code]
在标签里添加reversed来反序循环列表:
[code]{% for athlete in athlete_list reversed %}
...
{% endfor %}
{% for %}标签可以嵌套:
{% for country in countries %}
{{ country.name }}
{% for city in country.city_list %}
{{ city }}
{% endfor %}
{% endfor %}[/code]
系统不支持中断循环,如果你想这样,你可以改变你想遍历的变量来使得变量只包含你想遍历的值
类似的,系统也不支持continue语句,本章后面的“哲学和限制”会解释设计的原则
{% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息
1,forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:
[code]{% for item in todo_list %}
{{ forloop.counter }}: {{ item }}
{% endfor %}[/code]
2,forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3,forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
4,forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
5,forloop.first当第一次循环时值为True,在特别情况下很有用:
[code]{% for object in objects %}
{% if forloop.first %}
{% else %}
{% endif %}
{{ object }}
{% endfor %}[/code]
6,forloop.last当最后一次循环时值为True
[code]{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}[/code]
7,forloop.parentloop在嵌套循环中表示父循环的forloop:
[code]{% for country in countries %}
[b]注释[/b]
和HTML或编程语言如Python一样,Django模板语言允许注释{# #},如:
[code]{# This is a comment #}[/code]
模板渲染时注释不会输出,一个注释不能分成多行
下面的模板渲染时会和模板中的内容一样,注释标签不会解析成注释
This is a {# comment goes here
and spans another line #}
test.
[b]过滤器[/b]
本章前面提到,模板过滤器是变量显示前转换它们的值的方式,看起来像下面这样:
[code]{{ name|lower }}[/code]
这将显示通过lower过滤器过滤后{{ name }}变量的值,它将文本转换成小写
使用(|)管道来申请一个过滤器
过滤器可以串成链,即一个过滤器的结果可以传向下一个
下面是escape文本内容然后把换行转换成p标签的习惯用法:
[code]{{ my_text|escape|linebreaks }}[/code]
有些过滤器需要参数,需要参数的过滤器的样子:
[code]{{ bio|truncatewords:"30" }}[/code]
这将显示bio标量的前30个字,过滤器参数一直使用双引号
下面是一些最重要的过滤器:
1,addslashed,在任何后斜线,单引号,双引号前添加一个后斜线
当你把一些文本输出到一个JavaScript字符串时这会十分有用
2,date,根据一个格式化string参数来格式化date或datetime对象,例如:
[code]{{ pub_date|date:"F j, Y" }}[/code]
格式化string会在附录6定义
3,escape,避免给定的string里出现and符,引号,尖括号
当你处理用户提交的数据和确认合法的XML和XHTML数据时这将很有用
escape将作如下的一些转换:
[code]
Converts & to &
Converts < to <
Converts > to >
Converts "(双引号) to "
Converts '(单引号) to '
[/code]
4,length,返回值的长度,你可以在一个list或string上做此操作
或者在任何知道怎样决定自己的长度的Python对象上做此操作(即有一个__len__()方法的对象)
[b]在视图里使用模板[/b]
我们已经学习了使用模板系统的基础,现在我们来在前一章中的current_datetime视图中使用它:
[code]
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "It is now %s." % now
return HttpResponse(html)
[/code]
让我们把这个试图改成Django模板系统的做法,首先你可能想这样做:
[code]
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = Template("It is now {{ current_date }}.")
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
[/code]
这当然用到了模板系统,但它并没有解决我们本章开始介绍的问题,模板仍然嵌在Python代码里面
让我们通过把模板放在一个单独的文件里来解决它,一个简陋的方式就是把模板保存在文件系统中然后使用Python内建的文件读取功能得到模板的内容,下面来看看这样做的例子:
[code]
from django.template import Template, Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
# Simple, "dumb" way of saving templates on the filesystem.
# This doesn't account for missing files!
fp = open('/home/djangouser/templates/mytemplate.html')
t = Template(fp.read())
fp.close()
html = t.render(Context({'current_date': now}))
return HttpResponse(html)
[/code]
这种方式非常不优雅“
1,它不会处理丢失的文件,如果mytemplate.html不存在或者不可读,调用open()将触发IOError异常
2,它硬编码了你的模板位置,如果你使用这个技术来处理每个视图方法,你就会重复复制模板的位置
3,它引入了许多无聊代码,调用open(),fp.reand()和fp.close()需要很多输入而且毫无创造性
为了解决这个问题,我们将使用模板载入和模板目录
例如,你想myuser使用mypassword从任何主机连接到mysql服务器的话。
GRANT ALL PRIVILEGES ON *.* TO 'myuser'@'%'IDENTIFIED BY 'mypassword' WI
TH GRANT OPTION;
如果你想允许用户myuser从ip为192.168.1.6的主机连接到mysql服务器,并使用mypassword作
在 Service Pack 4 (SP 4), 是运行 Microsoft Windows Server 2003、 Microsoft Windows Storage Server 2003 或 Microsoft Windows 2000 服务器上您尝试安装 Microsoft SQL Server 2000 通过卷许可协议 (VLA) 媒体。 这样做, 收到以下错误信息CD KEY的 SQ
OS 7 has a new method that allows you to draw a view hierarchy into the current graphics context. This can be used to get an UIImage very fast.
I implemented a category method on UIView to get the vi
方法一:
在my.ini的[mysqld]字段加入:
skip-grant-tables
重启mysql服务,这时的mysql不需要密码即可登录数据库
然后进入mysql
mysql>use mysql;
mysql>更新 user set password=password('新密码') WHERE User='root';
mysq
背景
2014年11月12日,ASP.NET之父、微软云计算与企业级产品工程部执行副总裁Scott Guthrie,在Connect全球开发者在线会议上宣布,微软将开源全部.NET核心运行时,并将.NET 扩展为可在 Linux 和 Mac OS 平台上运行。.NET核心运行时将基于MIT开源许可协议发布,其中将包括执行.NET代码所需的一切项目——CLR、JIT编译器、垃圾收集器(GC)和核心