[TOC]
模板搜索机制
模板存放位置
- 每个app的templates文件夹
- settings.py参数TEMPLATES/DIRS设置路径
Django会自动去这两类文件夹中寻找模板。
但是,假如每个app的templates或者TEMPLATES定义路径中都有一个 index.html,
当在views.py中使用index.html模板时,直接写一个 render(request, 'index.html'),
或者当某个模板引用这个index.html模板时,直接写{% include/extends 'index.html' %},
Django 能不能找到想要的那个index.html呢?(答案是不一定能,有可能找错)
Django 模板查找机制:
Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。
所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,仅和该app相关的模板放在 app/templates/app/ 目录下面,这样,使用的时候,views templates引用模板就是"app1/index.html" 和 "app2/index.html" 这样有app作为名称的一部分,就不会混淆。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR,'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',
],
},
},
]
如果需要,写足够多的 block 以便继承的模板可以重写该部分,include 是包含其它文件的内容,就是把一些网页共用的部分拿出来,重复利用,改动的时候也方便一些,还可以把广告代码放在一个单独的html中,改动也方便一些,在用到的地方include进去。其它的页面继承自 base.html 就好了,继承后的模板也可以在 block 块中 include 其它的模板文件。
demo
# suynblog/learn/views.py
def home(request):
return render(request,'learn/home.html')
# suynblog/learn/urls.py
(r'^home/$',views.home,name='home'),
#suynblog/learn/templates/learn/base.html
{% block title %}NGS{% endblock %}
{% include 'learn/nav.html' %}
{% block content %}
这里是默认内容,所有继承自这个模板的,如果不覆盖就显示这里的默认内容。
{% endblock %}
{% include 'learn/bottom.html' %}
{% include 'learn/tongji.html' %}
# suynblog/learn/templates/home.html
{% extends 'learn/base.html' %}
{% block title %}欢迎光临首页{% endblock %}
{% block content %}
这里是首页,欢迎光临!
{% include 'add.html' %}
{% endblock %}
变量
一般的变量之类的用 {{ }}(变量)
字符串、列表、字典
# views.py
def home(request):
string = u"我在自强学堂学习Django,用它来建网站"
TutorialList = ["HTML", "CSS", "jQuery", "Python", "Django"]
info_dict = {'site': u'自强学堂', 'content': u'各种IT技术教程'}
return render(request,'learn/home.html',
{'string': string,'TutorialList': TutorialList,'info_dict': info_dict})
# home.html
{{ string }}
{% for i in TutorialList %}
{{ i }}
{% endfor %}
站点:{{ info_dict.site }} 内容:{{ info_dict.content }}
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
标签
功能类的,比如循环,条件判断是用 {% %}(标签)
1. if-elif-else-endif标签
模板中逻辑操作
==, !=, >=, <=, >, <,
and, or, not, in, not in
2. for-endfor标签
# views.py
List = map(str,range(100)) #int unicode str
# home.py
{% for item in List %}
{{ item }}
{% if not forloop.last %}
,
{% endif %}
{% endfor %}
for循环中变量forloop有很多有用的属性:
forloop.counter 索引从 1 开始算
forloop.counter0 索引从 0 开始算
forloop.revcounter 索引从最大长度到 1
forloop.revcounter0 索引从最大长度到 0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 用在嵌套的 for 循环中,获取上一层 for 循环的 forloop
当列表中可能为空值时用 for empty:
{% for athlete in athlete_list %}
- {{ athlete.name }}
{% empty %}
- 抱歉,列表为空
{% endfor %}
模板上得到对应视图网址:
# add.html
add3计算4+5
还可以使用 as 语句将内容取别名(相当于定义一个变量),多次使用(但视图名称到网址转换只进行了一次)
# add.html
{% url 'learn:add3' a=4 b=5 as add_url %}
add3计算4+5
模板中获取当前网址,当前用户等:
如果在 views.py 中用的是render_to_response函数,不是render函数时,需要将 request 加入到上下文渲染器。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR,'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',
],
},
},
]
根据'django.template.context_processors.request',在模板中我们就可以用request变量了。一般推荐用render而不是render_to_response。
- 获取当前用户
{{ request.user }}
# 如果登陆就显示内容,不登陆就不显示内容:
{% if request.user.is_authenticated %}
{{ request.user.username }},您好!
{% else %}
请登陆,这里放登陆链接
{% endif %}
- 获取当前网址及GET参数
{{ request.path }}
{{ request.GET.urlencode }}
#判断 delete 参数是不是 1 来删除当前的页面内容
当前网址加参数 delete