Django 模板

1. 模板的组成

  • HTML代码+逻辑控制代码

2. 逻辑控制代码的组成

2.1 变量格式: {{var_name}}

# 示例: Template 和 Context 对象
# Terminal
python manage.py shell      # 进入该django项目的环境
from django.template import Context, Template
t = Template('My name is {{ name }}')
c = Context({'name':'xiaohu'})
t.render(c)


# 同一模板,多个上下文,一旦有了模板对象,就可以通过它渲染多个context,无论何时我们都可以像这样
# 使用同一模板源渲染多个 context,只进行一次模板创建,然后多次调用 render()方法渲染会更为高效:

# 低效:
from name in ('小虎','小猪','旺仔'):
    t = Template('Hello, {{ name }}')
    print t.render(Context({'name': name}))

# 推荐
t = Template('Hello, {{ name }}')
from name in ('小虎','小猪','旺仔'):
    print t.render(Context({'name': name}))

2.2 万能的句点号

  • 到目前为止,我们通过context传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据
    结构,例如list,dictionary和自定义的对象。
  • 在Django模板中遍历复杂数据结构的关键是句点字符(.)
# 以下均在 iTerm 中操作

# 示例一:句点可用于访问列表索引
from django.template import Template, Context
t = Template('I have ate {{ items.2 }}')
c = Context({'items': ['apples', 'bananas', 'carrots']})
t.render(c)     # 输出: I have ate carrots

# 示例二:通过字典键访问字典的值,可以使用句点
from django.template import Template, Context
person = {'name':'xiaohu', 'age':'22'}
t = Template('{{ person.name }} is {{ person.age }} years old.')
c = Context({'person':person})
t.render(c)     # 输出: xiaohu is 22 years old.

# 示例三: 通过句点访问对象的属性.例如,Python中 datetime.date 对象有 year, month, day 几个属性
from django.template import Template, Context
import datetime
d = datetime.date(1998, 2, 18)

t = Template('The month is {{ date.month }} and the year is {{ date.year }}.')
c = Context({'date': d})
t.render(c)     # 输出: The month is 2 and the year is 1998.

# 示例四: 通过句点访问自定义对象的属性
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('Jhon', 'Smith')})
t.render(c)

# 示例五: 通过句点访问对象的方法
from django.template import Template, Context
t = Template('{{ var }} --- {{ var.upper }} -- {{ var.isdigit }}')
t.render(Context({'var':'hello'}))
# 输出: hello -- HELLO -- False
# 注意:
#   这里调用方法时,并没有使用圆括号,而且也无法给该方法传递参数;只能调用不需要参数的方法;

2.3 变量的过滤器(filter)

# 语法格式:
{{obj|filter:param}}

# param 的值:
    # add:      给变量加上相应的值;
    # addslashes: 给变量中的引号前加上斜线;
    # capfirst: 首字母大写;
    # cut:      从字符串中移除指定的字符;
    # date:     格式化日期字符串;
    # default:  如果值是False, 就替换成设置的默认值,否则就用本来的值;
    # default_if_none: 如果值是None,就替换成设置的默认值,否则就用本来的值;

# 示例:
# value1='aBcDe'
{{ value|upper }}<br/>

# value2=5
{{ value2|add:3 }}<br/>

# value3='he  llo wo r ld'
{{ value3|cut:' '}}<br/>

# import datetime
# value4=datetime.datetime.now()
{{ value4|date:'Y-m-d'}}<br/>

# value5=[]
{{ value5|default:'空的'}}<br/>

#value6='<a href="#">跳转</a>'
{{ value6 }}

{% autoescape off %}
    {{ value6 }}
{% endautoescape %}

{{ value6|safe }}<br/>

{{ value6|striptags }}

# value7='1234'
{{ value7|filesizeformat }}<br/>
{{ value7|first }}<br/>
{{ value7|length }}<br/>
{{ value7|slice:':-1'}}<br/>

2.4 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

  • {% tags %}
# 示例一: {% if %}
{% if num >= 100%}
    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}
{% elif num < 100 %}
    <p>num 小于100</p>
{% else %}
    <p>num 等于100</p>
{% endif %}


# 示例二:{% for %}
<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>

# 在标签里添加reversed,来反序循环列表
{% for obj in list reversed %}
    ....
{% endfor %}

# 系统不支持中断循环,也不支持continue语句, {% for %}标签内置了一个forloop模板变量,
# 这个变量含有一些属性可以提供一些关于循环的信息;

# forloop.counter 表示循环的次数,它从1开始计数,第一次循环设为1:
    {% for item in todo_list %}
        <p>{{ forloop.counter }}: {{ item }}</p>
    {% endfor %}

# forloop.counter0 类似于forloop.counter, 但它是从0开始计数,第一次循环设为0
# forloop.first 当第一次循环时,值为True:
    {% for object in objects %}
        {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}
        {{ object }}
        </li>
    {% endfor %}


# 示例三: {% csrf_token %}
# 用于生成 csrf_token 标签,用于防止跨站攻击验证;如果在view的index里用的是 render_to_response 方法,
# 不会生效;
# {% csrf_token %} 其实,这里生成一个 input 标签,和其他表单标签一起提交给后台;

<form action="{% url 'book' %}">
    <input type="text" name="username">
    <input type="password" name="pwd">
    <input type="submit" value="提交">
    {% csrf_token %}
</form>


# 示例四: {% with %} 用更简单的变量名替换复杂的变量名
{% with total=fhdhdfkldflkdf %}{{ total }}{% endwith %}

# 示例五: {% verbatin %} 原样输出
{% verebatim %}
    {{ hello }}
{% endverbatim %}

2.5 自定义 simple_tag

# 示例: 自定义filter 和 simple_tag

# Step1: 创建 mysite/templatetags 模块(名称固定)
# Step2: 在该文件夹下,创建任意 .py 文件,例如,my_tags.py
# Step3: 编写自定义代码 mysite/templatetags/my_tags.py
from django import template
from django.utils.safestring import mark_safe

register = template.Library()       # register 的名称是固定的,不可改变

@register.filter
def fitler_multi(v1, v2):
    return v1 * v2

@register.simple_tag
def simple_tag_multi(v1, v2):
    return v1 * v2

@register.simple_tag
def my_input(id, arg):
    result = "<input type='text' id='%s' class='%s' />" % (id, arg,)
    return mark_safe(result)

# Step4: 在html文件中,导入自定义的 my_tags.py
{% load my_tags %}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
    {{ num|filter_multi:2 }}

    {% simple_tag_multi 2 5 %}
</body>
</html>

# Step5: 在 settings 中的 INSTALLED_APPS 配置当前项目 mysite

# 注意:
#   filter 可以用在 if 等语句后, simple_tag 不可以
{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

2.6 extend 模板继承

  • 模板继承:就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载;
# 示例:
# Step1: 定义基础模板

# templates/base.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>

# 子模板的作用就是重载,添加或保留那些块的内容
# current_datetime.html
{% extends "base.html" %}

{% block title %}The current time{% endblock%}

{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}


# hours_head.html
{% extends "base.html"%}

{% block title %}Future time{% endblock %}

{% block content %}
<p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p>
{% endblock%}

参考资料:

原文地址:https://www.cnblogs.com/linkworld/p/8687007.html