7-模板系统
配置
(1)在总项目的settings.py中的TEMPLATES指定可用的模板
(2)创建Template对象,并提供字符串形式的模板代码
(3)调用Template对象的render方法,并传入字典上下文(Context)
模板后端的配置问题
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates',#指定模板引擎类的python路径 'DIRS': [os.path.join(BASE_DIR, 'templates')],#指定模板文件的存放路径 'APP_DIRS': True,#模板引擎会在已安装应用的templates子目录中查找 '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.contrib.auth.context_processors.auth',#用来在模板中访问用户和权限的上下文处理器 'django.contrib.messages.context_processors.messages',#用来支持消息应用的上下文处理器 ], }, }, ]
Template
from django.template import Template >>>Template("This is {{project}}")
Context
>>> from django.template import Context >>> b=Context({'project':'abc'}) >>> b['project'] 'abc'
render
>>> Template("this is {{project}}").render(Context({'project':'abcd'})) 'this is abcd'
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
使用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>templatestitle>
head>
<body>
<h1>Hello,I am is {{ project }}h1>
body>
html>
views.py
from django.template.loader import get_template def projecthtml(request): t = get_template('firstapp/temp.html')#获取模板,从文件系统中加载模板,只需要传递模板路径 html = t.render({'project':'诺言'})#render传递的是字典,不是Context对象 return HttpResponse(html)
path('html/temp/',views.projecthtml)
再次改写
from django.template.loader import get_template def projecthtml(request): #再次改写 return render(request,'firstapp/temp.html',{'project':'诺言丶诺言'})
render方法的含义: def render(request,template_name,context=None,content_type=None,status=None,using=None) content=loader.render_to_string(template_name,context,request,using=using) return HttpResponse(content,content_type,status)
RequestContext和上下文处理器
与普通的Context相比 (1)实例化需要一个HttpRequest对象,并作为第一个参数 (2)根据模板引擎配置的context_processors自动填充上下文变量
#处理器 def procontext(request): return {'project':'诺言'}#这里使用了HttpRequest类型的参数 from django.template import Template, RequestContext def prorescon(request): t = Template('{{project}},{{user.username}}
')#显示当前登录的用户 html=t.render(RequestContext(request,processors=[procontext])) return HttpResponse(html)
将处理器加入全局Templates
再次改写之前的方法,将render中的context去掉
def projecthtml(request): #再次改写 return render(request,'firstapp/temp.html')
改写之前的html文件
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>templatestitle>
head>
<body>
<h1>Hello,I am is {{ user.username }},{{ project }}h1>
body>
html>
模板语法
模板变量与替换规则
变量可以使任意字母、数字和下划线的组合,但是变量中不可以有空格或者标点符号
(1)字典查询{{a.b}}查询a['b']
(2)属性查询{{a.b}}查询a.b
(3)方法调用{{a.b}}查询a.b()
(4)数字索引查询{{a.1}}查询a[1]
1、字典查询
>>> from django.template import Template,Context >>> t = Template('hello:{{user.username}}') >>> user = {'username':'战神'} >>> c = Context({'user':user}) >>> t.render(c) 'hello:战神'
2、属性查询
>>> from django.template import Template,Context >>> import datetime >>> d=datetime.date(2019,12,8) >>> t=Template('time:{{date.year}}') >>> c=Context({'date':d}) >>> t.render(c) 'time:2019'
3、方法调用
>>> class A: ... def x(self): ... return 'django' ... def y(self,v='A的y'): ... return v ... y.alters_data = True #设置方法不被调用
...
>>> tem=Template('hello:{{a.x}},{{a.y}}') >>> text = Context({'a':A()}) >>> tem.render(text) 'hello:django,A的y'
当有异常时,可定义一个类
class hideException(Exception): silent_variable_failure = True #调用这个方法时则不会抛出异常
4、数字索引查询
>>> te=Template('hello:{{item.0}},{{item.1}}') >>> co=Context({'item':['我是0','我是1']}) >>> te.render(co) 'hello:我是0,我是1'
模板标签
if标签
语法结构如下:if和endif必须是成对存在的
{% if 表达式 %}
。。。。。。。。
{% elif 表达式 %}
。。。。。。。。
{% else %}
。。。。。。。。
{% endif %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>templatestitle>
head>
<body>
{% if user.username == 'xym' %}
<h1>Hello,I am is {{ user.username }},{{ project }}h1>
{% elif user.username == '战神'%}
<h1>Welcome,I am is {{ user.username }},{{ project }}h1>
{% endif %}
body>
html>
for标签
语法结构如下:for和endfor必须成对存在
{% for 项 in 数组 %}
。。。。。。。。。。。
{% empty %}当列表不存在时显示empty下的内容
。。。。。。。。。。。
{% endfor %}
def projecthtml(request, username): user = {'username': username} # 再次改写 return render(request, 'firstapp/temp.html', {'user': user, 'users': [ {'name': '诺言', 'password': '123456'}, {'name': '战神', 'password': '123456'}, {'name': '诺言', 'password': '123456'}, {'name': '战神', 'password': '123456'}, {'name': '诺言', 'password': '123456'}, {'name': '战神', 'password': '123456'}, ]})
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>templatestitle>
head>
<body>
{% if user.username == 'xym' %}
<h1>Hello,I am is {{ user.username }},{{ project }}h1>
{% elif user.username == '战神' %}
<h1>Welcome,I am is {{ user.username }},{{ project }}h1>
{% endif %}
<table border="1">
<tr>
<th>序号th>
<th>姓名th>
<th>密码th>
tr>
{% for item in users %}
<tr>
<td>{{ forloop.counter }}td>
{% comment %}计数,标记当前是第几个元素{% endcomment %}
<td>{{ item.name }}td>
<td>{{ item.password }}td>
tr>
{% empty %}
<tr>
<td>无用户td>
<td>无密码td>
tr>
{% endfor %}
table>
body>
html>
forloop还有几个属性:
(1)counter0:从0开始计数
(2)counter:从1开始计数
(3)revcounter:用来标识循环中剩余项,最后一次表达为1
(4)revcounter0:最后一次表达为0
(5)first:如果当前元素为第一个元素,为True,其余为False
(6)last:如果元素为最后一个元素,为True,其余为False
(7)parentloop:用于调用父级元素的forloop
url标签
语法结构如下:
{% url 视图的命名空间:视图函数 参数列表 %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Topic列表title>
head>
<body>
{% block content %}{% comment %}暂时还不知道是干嘛的,后面会详细讲{% endcomment %}
<h2>Topicsh2>
<ul>
{% for topic in object_list %} {% comment %}对传过来的modellist做each循环{% endcomment %}
<li>
<a href="{% url 'first:topic-detail' topic.id %}">{% comment %}将循环出来的id通过反向解析使用topic详情获取topic详情{% endcomment %}
{{ topic.title }}a>{% comment %}这里放每一个话题title{% endcomment %}
li>
{% endfor %}
ul>
{% endblock %}
body>
html>
comment标签
语法结构如下:
{% comment %}注释{% endcomment %}
变量是否相等的标签
{% ifuqeal v1 v2 %}True
。。。。。。。。。。。
{% else %}False
。。。。。。。。。。。
{% endifuqeal %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>templatestitle>
head>
<body>
{% ifequal user.username 'xym' %}
<h1>Hello,I am is {{ user.username }},{{ project }}h1>
{% else %}
<h1>Welcome,I am is {{ user.username }},{{ project }}h1>
{% endifequal %}
<table border="1">
<tr>
<th>序号th>
<th>姓名th>
<th>密码th>
tr>
{% for item in users %}
<tr>
<td>{{ forloop.counter }}td>
{% comment %}计数,标记当前是第几个元素{% endcomment %}
<td>{{ item.name }}td>
<td>{{ item.password }}td>
tr>
{% empty %}
<tr>
<td>无用户td>
<td>无密码td>
tr>
{% endfor %}
table>
body>
html>
自定义标签
准备
(1)在应用下创建一个python包templatetags,并创建custom_tags.py文件
(2)在settings中的INSTALLED_APPS将应用加入
#!/usr/bin/env python # -*- coding:utf-8 -*- from django import template register=template.Library()#一个有效的标签库必须有一个模板层变量register
@register.simple_tag(takes_context=True,name='index')#takes_context访问上下文字典,name此标签的名字
def prefix_tag(cur_str):
return 'hello %s'%(context['first'],cur_str)
自定义标签的使用,使用load标签声明:{% load custom_tags %}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自定义title>
head>
<body>
{% load custom_tags %}{% comment %}加载库标签{% endcomment %}
{% index '诺言' %}
<h1>{{ hello }}h1>
body>
html>