第八章 Django的模板

  1. MVC:model view(html) controller(控制器,路由传递指令,业务逻辑)

  2. MTV:model(ORM操作) template(html) view(业务逻辑)

  • {{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操作。

8.1. 变量

  1. 通过key取值

  2. 传值时,本质是字符串的替换

  3. .索引、.key、.属性、.方法

  4. 变量的 . 方法的优先级是:dict —> 属性、方法—>索引

  5. {{ 变量名 }}变量名由字母数字下划线组成。

  6. 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。

变量  {{  }}  
{% %} 表示逻辑相关的操作
对象调用__str__方法
.索引  .key  .属性  .方法
{{hobby.0}} ---索引不能写负的,只支持正向的 ---列表可以用索引取
{{dic.name}}
{{dic.keys}}---字典用.key直接取
{{dic.values}}

当模板中遇到一个(.)时,会按照如下的顺序去查询:1在字典中key查询,2属性或方法 3数字索引

 

8.1. 1 取值

1. 列表

  • hobby.索引只支持正向索引

hobby = ['movies', 'musics', 'reading', 'play badminton']
{{hobby.5}}

2. 字典

  • 通过key取值

  • 没有get方法。也可以使用request对象取值

  • 模版里方法不用加括号

hobby = ['movies', 'musics', 'reading', 'play badminton']
dic = {1: a, 2: b, 3: hobby}
{{ dic.3.1 }}
<br>
{{ dic.keys }}
<br>
{{ dic.values }}
<br>
{{ dic.items }}
<br>
{{ request }}

3. 类

  • 定义的方法不能使用形参,否则无法使用

# views.py中
class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age
    
  def talk(self):
    return '咱也不知道,咱也不敢问'
  def __str__(self):
      return '<Person obj: {}-{}>'.format(self.name, self.age)

 def my_test(request):
  person_obj = Person('henry', 19)
  return render(request, {'person_obj': person_obj})
{{ person_obj }}
<br>
{#此时talk不能传参#}
{{ person_obj.talk }}

 

8.1.2 filter(过滤器)

  • 作用:修改变量的显示结果

  • 语法:{{value|filter_name:参数}}

1. default

  • default用法,变量为False显示默认值

  • default和指定值之间不能有空格

<p>{{xxx}}</p>
<p>{{xxx|default:变量/指定值}}</p>
<p>{{xxx|default:''}}</p>
# settings.py中的templates中的options中设置
# 只有变量不存在时有效
'string_if_invalid' = '变量不存在'

2. filesizeformat

  • 文件默认byte为单位

  • 文件大小格式化

# 文件单位换算,最大有效单位为 PB
{变量|filesizeformat}

3. add

  • 数值加法

  • 字符串/list拼接

# 结果为6,优先使用数字的加法,有其他类型时,进行拼接
{{2|add:'4'}
hobby = ['movies', 'musics', 'reading', 'play badminton']
{{hobby|add:hobby}}
# add:hobby之间不能有任何空格,否则会报错

4. lower / upper / title(所有单词首字母大写)

5. ljust / rjust / center

"{{'Django'|center:"15" }}"
Ifvalueis"Django",theoutputwillbe" Django ".

6. length

  • 计算长度

string = 'hello bugs'
li = [1,2]
{{string|length}}
{{li|length}}

7. slice

  • stringlist

li = [1,2,3,4]
{{li|slice:'1:3'}}     # [2, 3]
{{ li|slice:'2' }}     # [1, 2]
{{ li|slice:'-1' }}    # [1, 2, 3]
{{li|slice:'-2::-1'}}  # [3, 2, 1]
{{ li |slice:'::-1' }} # [4, 3, 2, 1]

8. first /last

  • 取当前第一个或最后一个

{{li|last}}
{{li|first}}

9. join

{{li|join':'}}

10. truncatechars

  • 其后必须有参数,少于3时均为...

string = 'welcome to China, welcome to BeiJing'
{{string|truncatechars:'10'}}
# 会有三个点,也要占位
welcome...
{{string|truncatewords:'10'}} 
# 对中文无效,10个单词,10个单词+3个点

11. date

  • {{ value|date:"Y-m-d H:i:s"}}

  • django模版中的日期格式化,和python中不同

import datetime
now = datetime.datetime.now()
{{now|date:'Y-m-d H:i:s'}}
# settings.py

DATETIME_FORMAT = 'Y-m-d H:i:s' DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s' USE_L10N = False

12. safe/urlize

  • Django的模板中会对HTML标签和JS等语法标签进行自动转义

  • 安全,告诉Django不用做转义

  • 把非字符串类型转换为字符串类型

  • js、超链接

# 作为render传参中字典的元素
'value' : "<a href='#'>点我</a>"
{{ value|safe }}

13. divisibleby

{# 被2整除 #}
{{forloop.counter|divisibleby:2}}

8.1.3 自定义filter

  1. 在app下创建一个名为templatetags的python包(包名是固定的)

  2. 创建xxx.py 文件,文件名自定义(my_tags)

  3. 导入模块、注册register、添加装饰器

# app/templatetags/xxx.py
from django import template
# register 名称不能改变
register = template.Library()
# 参数可以省略,形参最多有两个r
@register.filter
def add_(value, arg):
  return '{}-{}'.format(value, arg)
# 使用
{% load my_tags %}
{{'henry'|add_:'hello'}}
  • 使用filter指定的函数名
# 定义
@register.filter(name='henry')
def add_(value, arg):
  return '{}-{}'.format(value, arg)
# 使用
{% load my_tags %}
{{'henry'|henry:'hello'}}
  • 取消转义
value = 'https://www.baidu.com'
# 自定义,不会转义
@register.filter(is_safe=True)
def add_(value, arg):
  return '{}{}'.format(value, arg=None)

# 自定义,不会转义
from django.utils.safestring import mark_safe
@register.filter
def add_(value, arg):
  return mark_safe('{}-{}'.format(value, arg))
  •  示例
加法{{ a }} + {{ b }} =
{{ a|add:b }}
<br>
减法
{{ a }} - 1 =
{{ a|add:-1 }}
<br>
乘法
{{ a }} * {{ b }} =
{% widthratio a 1 b %}
<br>
除法
{{ a }} * {{ b }} =
{% widthratio a b 1 %}
{% load show_a %}
<br>

 

8.2. 逻辑相关

8.2.1 for 循环

  • 没有则为空字典

  • for循环可用的一些参数:

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

 

 

1. 语法示例

  • {% empty %}

{# 整除,需要过滤器 #}
{% if forloop.counter|divisibleby:2 %}
{# 偶数行、偶数列 #}
{% if forloop.partent.forloop.counter|divisibleby:2 %}
{# 如果没有循环,显示empty中的内容 #}
{% empty %}
    <td colspan='5' style='text-algin:center'>没有数据<\td>

2. 示例

  • Template所需要的变量都由view中函数提供

{# hobby = ['movie', 'music', 'reading']
dic = [hobby, hobby, hobby] #}
{% for i in dic %}
    <tr>
        {% for i in i %}
                {% if forloop.counter|divisibleby:2 and forloop.parentloop.counter|divisibleby:2%}
                        <td style="color:red">
                              {{ i }}
                        </td>
                  {% else %}
                    <td>
                      {{ i }}
                    </td>
              {% endfor %}
        </tr>
        {% empty %}
                    {# colspan=4 表示合并单元格 #}
          <td colspan="4"style="text-align:center;">空空如也</td>
{% endfor %}

8.2.2 if 判断

  • if语句支持 and、or、==、>、 < 、!=、 <=、 >=、 in、 not in、 is、 is not

    • 逻辑运算(不支持连续判断)

    • 成员运算

    • 身份运算

  • 不支持 + (算术运算和连续判断),如有需求使用过滤器

{% if 条件判断 %}
    显示的内容
{% elif %}
    显示的内容
{% else %}
    显示的内容
{% endif %}
  • 连续判断对比
# python, 相当于,10 > 5 and 5 > 1, True
10 > 5 > 1
# js,相当于, 10 > 5 --> true, true(1) > 1,False
10 > 5 > 1
# 模版中,必须加上空格,10 > 5 --> true, true(1) > 1,False
10 > 5 > 1

8.2.3 with

  • 别名,只在with标签内部生效

li = [1,2,3,4]
{% with li.2 as x %}
    {{ x }}
{% endwith %}

{% with x=li.2 %}
{{ x }}
{% endwith %}

 

8.2.4 注释

  • 不做任何渲染

  • 即不替换任何元素

{# 任何效果都没有 #}
<!--html 注释,html渲染,页面不显示,元素中有-->

8.2.5 csrf_token

  • 跨站请求伪造,Cross-site request forgery

  • 这个Token的值必须是随机的,不可预测的。

{# form表单中加入 #}
{# form表单中有一个隐藏标签 #}
{% csrf_token %}
name = csrfmiddlewaretoken

Note(2)

  1. Django的模版语言不支持连续判断

  2. 属性的优先级大于方法

8.2.6 母版和继承

  • 母版:就是一个html页面,提取到多个页面的公共部分,并在页面中定义多个block

  • 普通的html页面,公共的部分提取出来,并定义block、用子页面替换

{# 母版 #}
{% block content %}
子页面的内容
{% endblock %}
  • 使用
{% extends 'base.html' %}
{% block content %}
    子页面
{% endblock %}

Note(4)

  1. 把{% extends 'base.html' %}写在第一行

  2. 如果想展示标签内容,需要写在block

  3. base.html需要引号,否则视为变量,可以在render中传入此变量

  4. 可以单独为css样式或js定义block

8.2.7 组件

  • 某一功能的html代码段

{# 某一块功能的拆解,只是某一段代码 #}
{% include 'component.html' %}

8.2.8 静态文件

  • 通过static寻找静态文件

{% load static %} {# 或 #} {% load staticfiles %} 
<link rel="stylesheet" href='{% static "css/dashboard.css" %}'>
  • 通过获取静态文件名
{% load static %} 
{% get_static_prefix %}
<link rel="stylesheet" href="{% get_static_prefix %}css/dashboard.css">
  • 给静态文件命别名
{% load static %}
{% get_static_prefix as file_path %}
<link rel="stylesheet" href="{{ file_path }}css/dashboard.css">

8.2.9 simple_tag

  • 自定义标签,对参数没有限制,较为灵活,类似自定义filter

  • 定义注册simpletag(标签)

# 与自定义filter在同一文件中
from django import template
@register.simple_tag(name='xxx')
def join_str(*args, **kwargs):
    return '{}--{}'.format('*'.join(args), '+'.join(kwargs.values()))
  • 使用方法
{# 与自定义filter在同一文件下,这里使用 my_tags.py #}
{% load my_tags %}
{# 注意关键字传参的变量 #}
{% xxx '1' '2' k1='v1' k2='v2' %}
  • 和filter的区别

    1. simpletag是标签,参数不受限制,使用{%%}

    2. filter是过滤器,参数最多有两个。使用{{ }}

    3. 装饰器不同

    4. 返回值不同

8.2.10 inclusion_tag

  • 最终返回html代码段

  • 可以用于分页

  • 返回值是必须是dict类型

# my_tag.py
@register.inclusion_tag('page.html')
def page(num):
  return {'num': range(1, num+1)}
{# page.html #}
{# bootstarp,组件中的分页代码 #}
<nav aria-label="Page navigation">
    <ul class="pagination">
        <li>
            <a href="#" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>
        {% for i in num %}
            <li><a href="#">{{ i }}</a></li>
        {% endfor %}
        <li>
            <a href="#" aria-label="Next">
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>
    </ul>
  • 在展示页面使用
{# xxx.html #}
{% load my_tags %}
{% page 10 %}

3. 自定义方法的使用流程

filter、simple_tag、inclusion_tag

1. 在已注册的App下建立templatetags的pyhton 包

2. 在包中,创建py文件

3. 在py文件中导入模块,并注册

from django import template
register = template.Library()

4. 写函数

@register.inclusion_tag('page.html')
def page(num):
  return {'num': range(1, num+1)}

5. 写模版

  • 组件是固定、不灵活

{# page.html #}
{% for i in num %}
    {{i}}
{% endfor %}

6. 使用

  • 在返回页面使用

{# filter #}
{% load my_tag %}
{{'xxx'|add_:'a'}}
{# simple_tag #}
{% load my_tag %}
{% join_str 1 2 k1='v1' k2='v2' %}
{# inclusion_tag #}
{% load my_tag %}
{% page 4 %}

 

posted @ 2020-05-20 11:22  炜琴清  阅读(190)  评论(0编辑  收藏  举报