Django模板语言

Django模板系统

官方文档


常用语法


{{ 变量名 }} 和 {% 变量名 %}

变量相关的用{{ 变量名 }},逻辑相关的用{% 变量名 %}

变量


在Django的模板语言中按此语法使用:{{ 变量名 }}。

当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。
点(.)在模板语言中有特殊的含义。当模版系统遇到点("."),它将以这样的顺序查询:

字典查询(Dictionary lookup)
属性或方法查询(Attribute or method lookup)
数字索引查询(Numeric index lookup)


注意事项:
1. 如果计算结果的值是可调用的,它将被无参数的调用。 调用的结果将成为模版的值。 2. 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串) 。

案例

urls.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^template_test/', views.template_test),
]

views.py

from django.shortcuts import render

# Create your views here.


def template_test(request):
    ls = [11, 21, 22]
    dic = {'name': '魏新雨咋软'}

    class Person(object):
        def __init__(self, name, age, dream):
            self.name = name
            self.age = age
            self.dream = dream

        def dream(self):
            return '{}的梦想是成为一个摄影师'.format(self.name)


    weixinyu = Person('魏新雨', 33, '魏新雨咋软')
    chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')

    return render(request, 'template_test.html', locals())

/templates/template_test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<h1>列表</h1>
{{ ls }}
<br>
<h2>取列表的索引</h2>
{{ ls.0 }}
{{ ls.1 }}
{{ ls.2 }}
<br>
<h1>字典</h1>
{{ dic }}
<br>
<h2>取字典的value</h2>
{{ dic.name }}
<br>
<h1>对象</h1>
<p>{{ weixinyu.name }}: 字 {{ weixinyu.dream }}</p>
<p>{{ chenjun.name }}: 字 {{ chenjun.dream }}</p>

</body>
</html>


Filters(过滤器)


在Django的模板语言中,通过使用 过滤器 来改变变量的显示。

过滤器的语法:

{{ value|filter_name:参数 }}

使用管道符|来应用过滤器。

例如:{{ name|lower }}会将name变量应用lower过滤器之后再显示它的值。lower在这里的作用是将文本全都变成小写。

注意事项:

1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
2. 过滤器可以接受参数,例如:`{{ sss|truncatewords:30 }}`,这将显示sss的前30个单词。
3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:`{{ list|join:', ' }}`
4. "|" 左右没有空格没有空格没有空格

### lower

将字符串转换成小写

{{ name2|lower }}


join

使用字符串连接列表,例如Python的str.join(list)

{{ ls|join:'-' }}


### default

设置默认值

{{ s14|default:'s14这个变量是个空值' }}


lenth

计算数据的长度

{{ ls|length }}


filesizeformat

将数值换成人类易读的文件的单位

{{ file_size|filesizeformat }}


### slice

切片

{{ name2|slice:'1:-1' }}
{{ name2|slice:'1:-1:2' }}


data

指定时间格式

{{ now|date:'Y-m-d H:i:s' }}


timesince

变量的时间距离现在的时间多久了, 变量的时间必须是过去的时间

{{ comment_date|timesince }}


timeuntil

现在距离变量的时间距离还有多久, 变量的时间必须是未来的时间

{{ from_date|timeuntil }}


### safe

将html字符串在浏览器渲染成html格式的数据(取消对html标签的转义)

{{ html|safe }}


truncatechars

如果截取的数量小于文本数量, 则最后三个字符会用...表示

{{ s1|truncatechars:5 }}


truncatewords

截取单词, 通过空格来区分单词, 如果截取的字符数小于数据的总长度, 则剩下的字符数用...来代替

{{ s1|truncatewords:7}}


cut

移除value中所有的与给出的变量相同的字符串

{{ s2|cut:' ' }}


divisibleby

如果value可以被给出的参数整除,则返回 True

{{ value|divisibleby:“2” }}
<p>{{ 4|divisibleby:'2' }}</p>
<p>{{ 3|divisibleby:'2' }} </p>


### **自定义filter**

定义

1. 在app目录下创建一个名为 templatetags 的python包
2. 在上面创建的包内部创建一个python文件: filter.py
3. 在filter.py文件中按照固定的格式注册的一个自定义的filter
from django import template

# 固定写法, 生成一个注册实例对象
register = template.Library()

@register.filter(name='generator_sb')  # 告诉django的模板语言, 现在注册一个自定义的filter, name属性则是指定模板语言调用它时候用的名字, 默认不指定是用函数名
def add_sb(value):
    '''
    给任意指定的变量添加sb
    :param value: | 左边被修饰的那个变量
    :return: 修饰后的内容
    '''
    return value + 'sb'

@register.filter()
def add_str(value, arg):
    return value + arg

使用

1. 重启Django项目
2. 在HTML页面中:{% load python文件名 %}
3. {{ name2|add_str:'大好人' }}


设置默认时间的显示格式

settings.py

USE_L10N = False

DATETIME_FORMAT = 'Y-m-d H:i:s'

{{ now }}


Tags(标签)


views.py

def template_test(request):
    ls = [11, 21, 22]
    dic = {'name': '魏新雨咋软'}
    name2 = 'WEI XINYU ZARUAN'
    file_size = 84987394875739397459
    now = datetime.datetime.now()
    html = '<a href="https://www.baidu.com">百度一下</a>'
    s1 = '世情薄人情恶雨送黄昏花易落'
    s2 = "Hello, man, how are you? thank you. And you"
    comment_date = now - datetime.timedelta(days=7)
    from_date = now + datetime.timedelta(days=7)

    lis = [
        ['魏新雨咋软', '陈骏啊, 萨宁啊', '傻人', '魏新雨咋软不累赛了'],
        ['魏新雨咋软2', '陈骏啊2, 萨宁啊2', '傻人2', '魏新雨咋软不累赛了2'],
        ['魏新雨咋软3', '陈骏啊3, 萨宁啊2', '傻人3', '魏新雨咋软不累赛了3'],
        ['魏新雨咋软4', '陈骏啊4, 萨宁啊2', '傻人4', '魏新雨咋软不累赛了4'],
    ]

    class Person(object):
        def __init__(self, name, age, dream):
            self.name = name
            self.age = age
            self.dream = dream

        def dream(self):
            return '{}的梦想是成为一个摄影师'.format(self.name)


    weixinyu = Person('魏新雨', 33, '魏新雨咋软')
    chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')

    # return render(request, 'template_test.html', locals())
    return render(request, 'index.html', locals())

需求1 偶数列变色

index.html

<table border="1px">
    <thead></thead>
    <tbody>
    {% for row in lis %}
       <tr>
      {% for name in row %}
          {% if forloop.counter|divisibleby:'2' %}
          <td style="color: green">{{ name }}</td>
              {% else %}
              <td>{{ name }}</td>
          {% endif %}
      {% endfor %}

       </tr>
    {% endfor %}

    </tbody>
</table>

需求2 偶数行变色

<table border="1px">
    <thead></thead>
    <tbody>
    {% for row in lis %}
       <tr>
      {% for name in row %}
          {% if forloop.parentloop.counter|divisibleby:'2' %}
          <td style="color: green">{{ name }}</td>
              {% else %}
              <td>{{ name }}</td>
          {% endif %}
      {% endfor %}

       </tr>
    {% endfor %}

    </tbody>
</table>

偶数行偶数列变色

<table border="1px">
    <thead></thead>
    <tbody>
    {% for row in lis %}
       <tr>
      {% for name in row %}
          {% if forloop.parentloop.counter|divisibleby:'2' and forloop.counter|divisibleby:'2' %}
          <td style="color: green">{{ name }}</td>
              {% else %}
              <td>{{ name }}</td>
          {% endif %}
      {% endfor %}

       </tr>
    {% endfor %}

    </tbody>
</table>


注意

模板语言不支持链式比较, 出现链式比较的时候, 比如说 a>b>c, 则会先计算a>b是True还是False, 然后在用0或者1与c再进行比较


{% if 2 > 1 == 1 %}
这是真的
    {% else %}
    这是假的
{% endif %}

输出结果

这是真的

{% if 2 > 1 > 1 %}
这是真的
    {% else %}
    这是假的
{% endif %}

输出结果

这是假的

if

{%  if  条件%}
    操作
{% endif %}

{%  if  条件%}
    操作

{% elif 条件 %}

{% else %}

{% endif %}

注意:
1. 不支持连续判断  a>b>c  a>b and b>c  
2. 不支持算数运算  + - * /    add 

for

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

for循环可用的一些参数:

Variable Description
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(到1结束)
forloop.revcounter0 当前循环的倒序索引值(到0结束)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

with

{% with 变量 as 别名%}
      
  {{ 别名 }}
{% endwith %}

Csrf token

1. 放在form表单中
2. 在表单中添加了一个隐藏的input标签
    name csrfmiddlewaretoken 
    valve  askjdaskdhashdkasd  64 

<input type="hidden" name="csrfmiddlewaretoken" value="2V2pQjIqT0ZDkSImSguofhdLRKAUPyIvZk7zLjzgtNgyna7gdGmoWjF1Rv7UuOBI">


自定义simpletag

/templatetags/simlpletag.py

from django import template

register = template.Library()


@register.simple_tag
def join_str(*args, **kwargs):
    print(args)
    print(kwargs)
    if args and not kwargs:
        return "_".join(args)
    if kwargs and not args:
        return "_".join((kwargs['k1'], kwargs['k2']))
    if kwargs and args:
        args_list = list(args)
        args_list.extend([kwargs.get('k1'), kwargs.get('k2')])

        return "_".join(args_list)

views.py

def template_test(request):
    ls = [11, 21, 22]
    dic = {'name': '魏新雨咋软'}
    name2 = 'WEI XINYU ZARUAN'
    file_size = 84987394875739397459
    now = datetime.datetime.now()
    html = '<a href="https://www.baidu.com">百度一下</a>'
    s1 = '世情薄人情恶雨送黄昏花易落'
    s2 = "Hello, man, how are you? thank you. And you"
    comment_date = now - datetime.timedelta(days=7)
    from_date = now + datetime.timedelta(days=7)

    lis = [
        ['魏新雨咋软', '陈骏啊, 萨宁啊', '傻人', '魏新雨咋软不累赛了'],
        ['魏新雨咋软2', '陈骏啊2, 萨宁啊2', '傻人2', '魏新雨咋软不累赛了2'],
        ['魏新雨咋软3', '陈骏啊3, 萨宁啊2', '傻人3', '魏新雨咋软不累赛了3'],
        ['魏新雨咋软4', '陈骏啊4, 萨宁啊2', '傻人4', '魏新雨咋软不累赛了4'],
    ]

    class Person(object):
        def __init__(self, name, age, dream):
            self.name = name
            self.age = age
            self.dream = dream

        def dream(self):
            return '{}的梦想是成为一个摄影师'.format(self.name)


    weixinyu = Person('魏新雨', 33, '魏新雨咋软')
    chenjun = Person('陈骏', 33, '陈骏啊, 萨宁啊')

    # return render(request, 'template_test.html', locals())
    return render(request, 'index.html', locals())

index.html

<h2>自定义simple_tag</h2>
{% load simlpletag %}
{% join_str '魏新雨' '咋软' '是' '个' '大好人' k1='魏新雨' k2='咋软'%}

### 自定义inclusion_tag

多用于返回html代码片段

1. 在app下创建一个templatetags的python包   templatetags名字不能错

2. 在包下写py文件 mypaginator

3. 编辑文件

4. 定义函数
可以接受参数
返回一个字典 

5. 函数上加装饰器  ---> @register.inclusion_tag('mypaginator.html')

from django import template

register = template.Library()

@register.inclusion_tag('mypaginator.html')
def mypaginator(total, current_num):
    total = range(1, total+1)
    current_num = current_num
    return locals()


6. 函数返回的字典 交给 pagination.html 渲染
      <!--分页开始-->
<div>
    <nav aria-label="Page navigation" class="pull-right">
        <ul class="pagination">
            <li>
                <a href="#" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                </a>
            </li>

            {% for num in total %}
                {% if num == current_num %}
                    <li class="active"><a href="#">{{ num }}</a></li>
                {% else %}
                    <li><a href="#">{{ num }}</a></li>
                {% endif %}

            {% endfor %}

            <li>
                <a href="#" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                </a>
            </li>
        </ul>
    </nav>
</div>
<!--分页结束-->


母版

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  {% block page-css %}
  
  {% endblock %}
</head>
<body>

<h1>这是母板的标题</h1>

{% block page-main %}

{% endblock %}
<h1>母板底部内容</h1>
{% block page-js %}

{% endblock %}
</body>
</html>

注意:我们通常会在母板中定义页面专用的CSS块和JS块,方便子页面替换


继承母板

{% extends 'layouts.html' %}

块(block)

通过在母板中使用{% block  xxx %}来定义"块"
在子页面中通过定义母板中的block名来对应替换母板中相应的内容
{% block page-main %}
  <p>世情薄</p>
  <p>人情恶</p>
  <p>雨送黄昏花易落</p>
{% endblock %}

组件

1. 写一段的代码  nav.html
2. {% include 'nav.html' %}

静态文件相关

1. {% load static %}
static 是个变量, 会获取settings中获取STATIC_URL的值

2. {% static  '相对路径' %}   ——》 去settings中获取STATIC_URL  '/alias/' 和相对路径进行拼接
<link href="{% static "bootstrap-3.3.7/css/bootstrap.css" %}" rel="stylesheet">

3. {% get_static_prefix %}    ——》 去settings中获取STATIC_URL  '/alias/'
"{% get_static_prefix %}相对路径"
<link href="{% get_static_prefix %}dashboard.css" rel="stylesheet">


案例

图书管理系统源码

posted @ 2019-10-25 15:18  cjw1219  阅读(286)  评论(0编辑  收藏  举报