58 Django--模板系统

Posted yzm1017

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了58 Django--模板系统相关的知识,希望对你有一定的参考价值。

模板渲染系统

官方文档

1. 语法

可做动态页面----字符串替换。

 变量     ---变量相关
% 逻辑 %    ---逻辑相关

2. 变量 变量名

当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。

变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。

万能的点("."):可以取字符串,字典,列表的索引位置,类对象的属性、方法(不能传参)...

当模版系统遇到点("."),它将以这样的顺序查询:

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

urls.py

def test(request):

    name = '24期'
    lst = ['aa', 'bb', 'cc', 'dd']
    dic = 'k1':'v1', 'k2':'v2'
    num = 110
    class Person(object):
        p = '人类'
        def dream(self):
            return 'dreamer'
    obj = Person()

# 方式一:
    return render(request, 'test.html', 'name':name,'lst':lst,'dic':dic,'obj':obj)
    # 传参数(字典形式) 模板渲染,在回复浏览器之前做的事情
# 方式二:
    return render(request, 'test.html', locals())           #locals()获取函数内所有的变量,共同通过render方法交给test.html文件进行模板渲染,效率较低

test.html文件:

? 调用对象里面的方法的时候,不需要写括号来执行,并且只能执行不需要传参数的方法,如果你的这个方法需要传参数,那么模板语言不支持、不渲染。

<body>
<h1>name</h1>       
<h2>lst.1</h2>      <!--取索引位置1的数据-->
<h2>dic.键</h2>      <!-- 获取值-->
<h2>dic.keys</h2>   <!--所有的键 dict_keys(['k1', 'k2'])-->
<h2>dic.values</h2> <!--所有的值 dict_values(['v1', 'v2'])-->
<h2>dic.items</h2>  <!--dict_items([('k1', 'v1'), ('k2', 'v2')])-->
<h2>  obj  </h2>    <!-- <app01.views.test.<locals>.Person object at 0x000002177B42EE80> -->
<h2>  obj.p  </h2>  <!-- 取类属性属性值 -->
<h2>  obj.dream  </h2>  <!--调用类的方法,不能传参-->
</body>

3. 过滤器(内置)

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

语法:

 value|过滤器:参数 

注意事项:

  1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
  2. 过滤器可以接受参数, 冒号: 后面接参数。
  3. 过滤器参数包含空格的话,必须用引号包裹起来。比如join过滤器。
  4. “|”左右两边不能有空格

default

 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值,无法找到。

 value|default:"nothing" 
# 如果value没有传值或者值为空的话就显示nothing

length

? 返回值的长度,作用于字符串和列表。

 value|length           # 长度

filesizeformat

? 将书值格式化为一个 “人类可读的” 文件尺寸(13kb,4MB)

 value|filesizeformat 
 # 如果 value 是 123456789,输出将会是 117.7 MB。

slice

? 切片,除了字符串,还有其他可切片的数据类型

 value|slice:"1:3" 

date

 格式化,如果 value=datetime.datetime.now()

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

safe

将字符串的标签识别成标签。

value = "<a href=‘#‘>点我</a>"

 value|safe 

truncatechars

如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。

参数:截断的字符数

 value|truncatechars:9  
#注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,那怎么展开啊,配合前端的点击事件就行啦

truncatewords

在一定数量的字后截断字符串,是截多少个单词。(按空格取)

例如:‘hello girl hi baby yue ma’,

 value|truncatewords:3  #上面例子得到的结果是 'hello girl h1...'

cut

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

 value|cut:' ' 
# 移除空格  如果value为'i love you',那么将输出'iloveyou'.

join

使用字符串连接列表中的数据。

 list|join:'_' 
# 像Python的str.join(list)

timesince

将日期格式设为自该日期起的时间(例如,“4天,6小时”)。

  采用一个可选参数,它是一个包含用作比较点的日期的变量(不带参数,比较点为现在)。 例如,如果blog_date是表示2019年6月1日午夜的日期实例,并且comment_date是2019年6月1日08:00的日期实例,则以下将返回“8小时”:

 blog_date|timesince:comment_date 

timeuntil

? 似于timesince,除了它测量从现在开始直到给定日期或日期时间的时间。

还能够计算周数。 例如,如果今天是2019年6月1日,而conference_date是2019年6月29日的日期实例,则 conference_date | timeuntil 将返回“4周”。

  使用可选参数,它是一个包含用作比较点的日期(而不是现在)的变量。 如果from_date包含2019年6月22日,则以下内容将返回“1周”:

 conference_date|timeuntil:from_date 

示例:

views.py 文件

def test(request):
    import datetime
    
    date = datetime.datetime.now()
    
    blog_date = datetime.datetime(2019,9,25,00,00,00)
    comment_date = datetime.datetime(2019,9,26,18,00,00)
    conference_date = datetime.datetime(2019,9,1,00,00,00)
    from_date = datetime.datetime(2019,9,30,00,00,00)
    
    file_size = 123456789
    a = "<a href='http://www.baidu.com' target='_blank'>百度</a>"
    
    english = 'I love you my lover!'
    lst = ['aa', 'bb', 'cc', 'dd']

    flag = False

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

test.html文件:

<body>

<p> flag|default:'这是空!' </p>    # 这是空! #

<p> lst|length </p>  # 4 #

<p> file_size|filesizeformat </p>  # 117.7MB #

<p> english|slice:"0:2" </p>    # I #

<p> date|date:"Y-m-d H:i:s" </p>    
    # 2019-09-25 18:13:14 #

<p> a|safe </p>     # 百度  能够识别a标签 #

<p> english|upper </p>  # 全部大写 #

<p> english|truncatechars:9 </p>  # I love... #

<p> english|truncatewords:3 </p>  # I love you ... #

<p> english|cut:' ' </p>    # Iloveyoumylover! #

<p> lst|join:'_' </p>   # aa_bb_cc_dd #

<p> blog_date|timesince:comment_date </p>
    # 1 day, 18 hours #

<p> conference_date|timesince:from_date </p>
    # 4 weeks #

<p> date|timesince:from_date </p>
    # 3 days, 17 hours #
  
</body>

4. 标签 -- % tag %逻辑

% tag % % endtag %

for标签

? 遍历每一个元素: 写个for,然后 tab键自动生成for循环的结构,循环很基础,就这么简单的用,没有什么break之类的,复杂一些的功能,你要通过js

<ul>
    % for i in list %
        <li> i </li>
    % endfor %
</ul>

# % for i in list reversed %反向完成循环

循环序号可以通过{{forloop}}显示,必须在循环内部用 

forloop.counter     当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0    当前循环的索引值(从0开始)
forloop.revcounter  当前循环的倒序索引值(从1开始)
forloop.revcounter0  当前循环的倒序索引值(从0开始)
forloop.first   当前循环是不是第一次循环(布尔值)
forloop.last   当前循环是不是最后一次循环(布尔值)
forloop.parentloop  本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等

示例:

lst = [‘你好‘,‘Hello‘,‘世界‘, ‘word‘]

<body>
    <ul>    
        % for i in lst %        
            <li> forloop.counter --- i  </li>    
        % endfor %</ul></body>

结果:
1---你好
2---Hello
3---世界
4---word

嵌套:

dic = ‘k1‘:‘v1‘, ‘k2‘:‘v2‘, ‘k3‘:[1,2,3,4,5]

<ul>
% for i in dic %
        % for k,v in dic.items %
            <li> forloop.counter -- forloop.parentloop.counter  ===  k  --  v </li>
        % endfor %
    % endfor %
</ul>

结果:
1--1 === k1 -- v1
2--1 === k2 -- v2
3--1 === k3 -- [1, 2, 3, 4, 5]
1--2 === k1 -- v1
2--2 === k2 -- v2
3--2 === k3 -- [1, 2, 3, 4, 5]
1--3 === k1 -- v1
2--3 === k2 -- v2
3--3 === k3 -- [1, 2, 3, 4, 5]

for ... empty

for 标签带有一个可选的% empty % 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。

% for person in person_list %
    <p> person </p>
    % empty %
        <p>没有找到东西!</p>
% endfor %
    

if 标签

% if %会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。

% if num > 100 or num < 0 %
    <p>成绩无效!</p>
% elif num > 80 and num <= 100 %
    <p>成绩优秀</p>
% else %
    <p>一般般</p>
% endif %

结合过滤器使用

% if user_list|length > 5 %  <!--结合过滤器来使用-->
  <p>七座豪华SUV</p>
% else %
    <p>黄包车</p>
% endif %

with 标签

使用一个简单地名字缓存一个复杂的变量,多用于给一个复杂的变量起别名。

with: 等号两边不能有空格

% with total=business.employees.count %
     total  <!--只能在with语句体内用-->
% endwith %

with...as... 效果一样

% with business.employees.count as total %
     total 
% endwith %

示例:

dic = ‘k1‘:‘v1‘, ‘k2‘:‘v2‘, ‘k3‘:[1,2,3,4,5]

% with d=dic.k3.2 %
     d 
% endwith %

% with dic.k3.3 as d1 %
     d1 

% endwith %

5. 模板继承

继承

extends 标签是关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先,它将定位父模版。

然后通过block 标签中的名字,将父模板对应的block标签替换。

不能在一个模版中定义多个相同名字的 block 标签。

% extends 'muban.html'    # 继承muban.html页面,必须写


# 预留钩子,供其他需要继承它的html页面,能够自己自定义某些内容
# content是名字,便于子页面对应替换,子页面也要写对应钩子(开块替换内容)。
% block content %
    ...
% endblock content %


% block css %
     block.super 
    # 将子页面的内容和继承的母版中block里面的内容同时保留
% endblock css %


% block js %
    ...
% endblock js %

组件

可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方,文件的任意位置按如下语法导入即可。

% include '组件文件' %    

例:
    % include 'navbar.html' %     # 引用组件

组件和插件的简单区别:

组件是提供某一完整功能的模块,如:编辑器组件,QQ空间提供的关注组件 等。

而插件更倾向封闭某一功能方法的函数。

这两者的区别在 javascript 里区别很小,组件这个名词用得不多,一般统称插件。

自定义标签和过滤器

自定义过滤器

  1. app应用文件夹中创建一个templatetags文件夹,必须是这个名字
  2. 在templatetags文件夹中创建一个自定义py文件,如mytag.py
  3. 在py文件中创建自定义过滤器
  4. html文件中使用
  5. 注意:参数最多两个

自定义mytag.py文件

from django import template
register = templatr.Library()   # 固定的名字register

@register.filter
def my_filter(v1,v2):   # v1接收管道符'|'前的参数
    """
    有参数的过滤器,最多两个参数
    :param v1: 接收管道符前的参数
    :param v2: 接收过滤器冒号后的参数
    :return:v1+v2
    """
    return v1+v2        # 两个字符串拼接

tag.html文件:

% load 文件 %   # 加载py文件

% load mytag %
 name|my_filte:参数   # 接收views视图函数的参数(替换)


示例:
% load mytag %
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<h1>
     name|my_filter:'sb' 
</h1>
</body>
</html>

views视图函数

def tag(request):
    name = 'alex'
    return render(request, 'tag.html', 'name': name)

自定义标签

  1. app应用文件夹中创建一个templatetags文件夹,必须是这个名字
  2. 在templatetags文件夹中创建一个自定义py文件
  3. 创建自定义标签
  4. html文件中使用
  5. 注意:参数可传多个

mytag.py文件

from django import template
register = templatr.Library()   # 固定的名字register

@register.simple_tag
def my_tag(v1, v2):     

    return v1+v2        # 字符串拼接

tag.html文件

% load mytag %        # 加载 mytag.py文件,放在最上面

% my_tag name '帅比' %      # 标签 参数1 参数2 参数3...

views视图函数

def tag(request):
    name = 'alex'
    
    return render(request, 'tag.html', 'name': name)

inclusion_tag标签

多用于返回html代码片段。

  1. 创建一个result.html文件,
<body>
<ul>
    % for i in lst %
    <li> i </li>
    % endfor %
</ul>
</body>
  1. views视图:
def inclusion_tag(request):

    lst = [11, 22, 33, 44, 55]
    return render(request, 'inc_tag.html', 'lst': lst)
  1. 在mytag.py文件中,写inclusion_tag标签
from django import template
register = template.Library()

@register.inclusion_tag('result.html')  # 将result.html里面的内容用下面函数的返回值渲染,然后作为一个组件一样,加载到使用这个函数的html文件里面

def in_tag(v1):     # 接收in_tag.html文件中的lt参数

    return 'lst': v1      # 将lst交与result.html文件渲染
  1. 创建in_tag.html文件
% load mytag %        # 加载mytag.py文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>

</head>
<body>

% in_tag lt %     # 替换mytag.py中的in_tag函数,接收lst参数

</body>
</html>

静态文件配置

  1. 首先在项目路径下创建一个文件夹,如:statics

  2. 在文件夹下创建css等文件夹,并创建静态文件,如:test.css

  3. 在settind中配置静态文件路径

    在 STATIC_URL = ‘/static/‘ (静态文件路径别名)下面写:

STATICFILES_DIPS=[
    os.path.join(BASE_DIR,'statics')
]
  1. 在html文件中引入css文件,也可以引入bootstrap框架
<link rel="stylesheet"  href='/static/css/test.css'>
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

以上是关于58 Django--模板系统的主要内容,如果未能解决你的问题,请参考以下文章

无法运行 Django 模板引擎 - Django

Python之路58-Django安装配置及一些基础知识点

Django:租户的模板路径问题

Django框架-Django模板(template)系统

Django:模板和迭代字典

如何检查Django中是不是存在模板?