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>