模板
上节我们直接将html内容写在代码中直接输出,这样不利于html代码的复用和维护,所以需要模板系统来实现html代码和数据的分离,接下来我们就来学习Django中的模板系统。
- 模板版Hello Django!
- Django 模板教程
- 加载静态资源
模板版Hello Django!
接着上节的HelloDjango项目,我们在HelloDjango目录下新建templates文件夹,然后在templates下新建index.html文件,文件内容如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello Django!</title>
</head>
<body>
{{context}}
</body>
</html>
同时修改view.py的hello函数,修改后文件如下:
from django.shortcuts import render
def hello(request):
return render(request,'index.html',{'context':'Hello Django!'})
然后我们需要在settings.py文件里设置模板文件夹路径,让Django可以找到,添加以下代码:
1.8版本前
TEMPLATE_DIRS={
os.path.join(BASE_DIR,'HelloDjango/templates')
}
1.8版本及以后
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# templates 文件夹路径
'DIRS': [os.path.join(BASE_DIR,'HelloDjango/templates'),],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
接下来需要同步数据库(上节没做),不执行可能会报错,执行以下命令
1.7版本前
python manage.py syncdb
1.7版本及往后
python manage.py migrate
然后启动服务,执行命令
python manage.py runserver 0.0.0.0:8000
再次访问即可看到同样的内容。
Django 模板教程
上面介绍了模板的简单使用,先来简单的解读下上诉代码,html中{{context}}是一个变量,render(request,‘index.html’,{‘context’:‘Hello Django!’})的时候后面字典参数指定context的值,前面参数指定了模板的文件名。
接下来我们介绍模板的基本语法
- 用{{}}包围的是变量,如{{context}},上面的例子中,我们给模板context传递了简单的值,大部分是string,以及一个datetime.date。尽管如此,模板可以传递更复杂的数据结构,如列表,字典和自定义对象模板中使用符号‘.’来访问复杂变量的成员(包括方法(无参数),字典的key,当方法发送异常时,字符串将会被渲染为空字符串),如上述代码修改为:
return render(request,'index.html',{'context':{'text':'Hello Django!'}})
在html中可以通过{{context.text}}来获取text的值,并且.符号可以嵌套使用。对于不合法的方法和变量,模板都会将其渲染为空字符串。
- 用{%%}包围的是块标签,如{%if True%},块标签的含义很丰富,Django模板支持多种内建的块标签,并且你可以写你自己的标签来扩展模板的功能,下面介绍常用的几个标签:
if/else
{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值系统则会显示{% if %}到{%else%}(如果存在)或{% endif %}(不存在)间的所有内容:
{% if today_is_weekend %}
<p>Welcome to the weekend!</p>
{% else %}
<p>Get back to work.</p>
{% endif %}
{% if %}标签接受and,or或者not来测试多个变量值或者否定一个给定的变量,但是不允许在一个标签块同时使用and 和 or(可以多次都使用and或or),如果要实现该功能,需使用嵌套{%if%}来完成,同样不存在{%elif%}标签,实现此功能同样需要嵌套。
for
{% for %}标签允许你按顺序遍历一个序列中的各个元素
Python的for语句语法为for X in Y,X是用来遍历Y的变量
每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容,如
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% endfor %}
</ul>
如需反向遍历,可以在标签添加reversed,用法如下:
{% for athlete in athlete_list reversed%}
<li>{{ athlete.name }}</li>
{% endfor %}
标签不支持break和continue,如果需要实现功能,请传递只包含想要遍历的变量的字典。
{% for %}标签内置了一个forloop模板变量,这个变量含有一些属性可以提供给你一些关于循环的信息
1.forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1,例如:
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
2.forloop.counter0类似于forloop.counter,但它是从0开始计数,第一次循环设为0
3.forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1
4.forloop.revcounter0类似于forloop.revcounter,但它是表示的数量少一个,即最后一次循环时设为0
5.forloop.first当第一次循环时值为True
6.forloop.last当最后一次循环时值为True
7.forloop.parentloop在嵌套循环中表示父循环的forloop:
{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }} </td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>
{% endfor %}
ifequal/ifnotequal
{% ifequal %}比较两个值,类似于{%if%}标签,同样支持{%else%},{%ifnotequal%}与{%ifequal%}相反
include模板标签
这个标签允许你引入另一个模板的内容,标签的参数是你想引入的模板的名字,名字可以是变量,也可以是单引号或双引号表示的string
下面两个例子引入了模板nav.html的内容,这表示单引号和双引号都是允许的:
{% include 'nav.html' %}
{% include "nav.html" %}
{% include template_name %} #template_name为变量,由渲染时动态指定
如果被引入的模板中包含任何的模板代码,如标签和变量等,它将用父模板的context计算它们
如果给定的模板名不存在,Django将做下面两件事情中的一件:
1.如果DEBUG设置为True,你将看到一个TemplateDoesNotExist异常的错误页面
2.如果DEBUG设置为False,标签将什么也不显示
模板继承
在web开发过程中,我们经常会遇到header或者footer相同的页面,django中可以使用模板继承来减少这些相同页面的冗余编码,这里先介绍下,具体如何使用会在后面的blog项目中介绍。
哲学和限制
Django的模板可能不同于jsp等其他模板引擎,他不允许你直接在模板中使用python代码,有时候为了实现某些功能可能需要很多代码(如if elif),但是这是django设计者所尊崇的设计哲学,业务逻辑应该和呈现逻辑分离,显示只做显示的事,业务的逻辑应交由后台来完成。当然你觉得Django的模板系统不好用的话,你也可以使用其他模板系统(1.8版本以后),具体做法为(更换为jinja2引擎):
在项目下建立jinja2_env.py
#from __future__ import absolute_import # 如果是py2就取消这行的注释
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
env.globals.update({
'static': staticfiles_storage.url,
'url': reverse,
})
return env
在settings.py里配置
#1.8版本及以后
TEMPLATES = [
{
#修改为其他模板引擎
'BACKEND': 'django.template.backends.jinja2.Jinja2',
# templates 文件夹路径
'DIRS': [os.path.join(BASE_DIR,'HelloDjango/templates'),],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
'environment': 'APP_NAME.jinja2_env.environment',#配置环境
},
},
]
加载静态资源
html中通常需要加载图片和css/js等静态资源,需要做以下配置
在settings.py中添加以下代码:
STATIC_ROOT = os.path.join(BASE_DIR,'blog/static')#static目录
STATIC_URL = '/static/'#访问的url
STATICFILES_DIRS = (
("css", os.path.join(STATIC_ROOT,'css')),
("js", os.path.join(STATIC_ROOT,'js')),
("images", os.path.join(STATIC_ROOT,'images')),
)#static文件夹
在html中这样使用
<link href="{{STATIC_URL}}css/base.css" rel="stylesheet">
这样即可加载css文件,图片和js文件类似,其中{{STATIC_URL}}为settings.py中设置的STATIC_URL值,django模板会自动传入这个值。
参考链接:
- http://blog.csdn.net/zhangxinrun/article/details/8095118/
- http://blog.csdn.net/baidu_35085676/article/details/77206901