第五章 Django框架——模板层Templates

第五章 Django框架——模板层Templates

一、MTV模式与MVC模式

二、模板语法之变量

三、模板语法之过滤器filter

四、模板语法之tags(与逻辑相关的)

五、模板之母版继承之block与extends

六、模板之母版导入之include(组件)

七、自定义simpletag

一、MTV模式与MVC模式

MVC模式

MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。

Django的MTV模式

Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性。

Django框架的不同之处在于它拆分的三部分为:Model(模型)、Template(模板)和View(视图),也就是MTV框架。

  • Model(模型):负责业务对象与数据库的对象(ORM)
  • Template(模版):负责如何把页面展示给用户
  • View(视图):负责业务逻辑,并在适当的时候调用Model和Template
  • 此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

二、模板语法之变量

只需要记两种特殊符号:

{{ filter }}和 {% tag %}

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

1.变量

语法:

{{ 变量名 }}

构成:

变量名由字母数字和下划线组成。

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

基本使用:

注意:

如果页面输入一个没有赋值的变量,页面上将不会显示它

方法:

A)列表操作

 ①按索引去列表值

B)字典操作

 ①按key取值

C)对象操作

 ①直接调用对象(也可以用__str__方法控制打印格式)

  结果:

 ②获取对象属性

 ③获取对象方法(只能调用不带参数的方法,因为没有办法加括号)

三、模板语法之过滤器filter

语法:

{{ value|filter_name:参数 }}

切记:

'|'左右没有空格没有空格没有空格

方法:

①default  如果value值没传的话就显示default的内容

# 如果value值没传的话就显示nothing
{{ value|default: "nothing"}}

②length  返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

<p>{{ name|length }}</p>

 ③filesizeformat  将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)。

{{ value|filesizeformat }}

 

 

 ④slice  切片 可以切列表,字符串

{{value|slice:"2:-1"}}

 ⑤date  格式化时间

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

 ⑥safe 告诉浏览器我这段代码是完全安全的

 Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

比如:

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

{{ value|safe}}

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

参数:截断的字符数

{{ value|truncatechars:9}}

 ⑧trunctewords  将字符串转换为省略表达式

{ 'This is a pen' | truncatewords:2 }}返回
This is ...

 ⑨其他(了解即可)

过滤器 描述 示例
upper 以大写方式输出 {{ user.name | upper }}
add 给value加上一个数值 {{ user.age | add:”5” }}
addslashes 单引号加上转义号  
capfirst 第一个字母大写 {{ ‘good’| capfirst }} 返回”Good”
center 输出指定长度的字符串,把变量居中 {{ “abcd”| center:”50” }}
cut 删除指定字符串 {{ “You are not a Englishman” | cut:”not” }}
date 格式化日期  
default 如果值不存在,则使用默认值代替 {{ value | default:”(N/A)” }}
default_if_none 如果值为None, 则使用默认值代替  
dictsort 按某字段排序,变量必须是一个dictionary {% for moment in moments | dictsort:”id” %}
dictsortreversed 按某字段倒序排序,变量必须是dictionary  
divisibleby 判断是否可以被数字整除
{{ 224 | divisibleby:2 }}  返回 True
escape 按HTML转义,比如将”<”转换为”&lt”  
filesizeformat 增加数字的可读性,转换结果为13KB,89MB,3Bytes等
{{ 1024 | filesizeformat }} 返回 1.0KB
first 返回列表的第1个元素,变量必须是一个列表  
floatformat 转换为指定精度的小数,默认保留1位小数 {{ 3.1415926 | floatformat:3 }} 返回 3.142  四舍五入
get_digit 从个位数开始截取指定位置的数字 {{ 123456 | get_digit:’1’}}
join 用指定分隔符连接列表 {{ [‘abc’,’45’] | join:’*’ }} 返回 abc*45
length 返回列表中元素的个数或字符串长度  
length_is 检查列表,字符串长度是否符合指定的值 {{ ‘hello’| length_is:’3’ }}
linebreaks 用<p>或<br>标签包裹变量 {{ “Hi David”|linebreaks }} 返回<p>Hi</p><p>David</p>
linebreaksbr 用<br/>标签代替换行符  
linenumbers 为变量中的每一行加上行号  
ljust 输出指定长度的字符串,变量左对齐 {{‘ab’|ljust:5}}返回 ‘ab   ’
lower 字符串变小写  
make_list 将字符串转换为列表  
pluralize 根据数字确定是否输出英文复数符号  
random 返回列表的随机一项  
removetags 删除字符串中指定的HTML标记 {{value | removetags: “h1 h2”}}
rjust 输出指定长度的字符串,变量右对齐  
slice 切片操作, 返回列表 {{[3,9,1] | slice:’:2’}} 返回 [3,9]
{{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’
slugify 在字符串中留下减号和下划线,其它符号删除,空格用减号替换
{{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23
stringformat 字符串格式化,语法同python  
time 返回日期的时间部分  
timesince 以“到现在为止过了多长时间”显示时间变量 结果可能为 45days, 3 hours
timeuntil 以“从现在开始到时间变量”还有多长时间显示时间变量  
title 每个单词首字母大写  
truncatewords 将字符串转换为省略表达方式
{{ 'This is a pen' | truncatewords:2 }}返回
This is ...
truncatewords_html 同上,但保留其中的HTML标签
{{ '<p>This is a pen</p>' | truncatewords:2 }}返回
<p>This is ...</p>
urlencode 将字符串中的特殊字符转换为url兼容表达方式 {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}}
urlize 将变量字符串中的url由纯文本变为链接  
wordcount 返回变量字符串中的单词数  
yesno 将布尔变量转换为字符串yes, no 或maybe
{{ True | yesno }}
{{ False | yesno }}
{{ None | yesno }}
返回 
yes
no 
maybe

 

自定义filter:

自定义过滤器只是带有一个或两个参数的Python函数:

  • 变量(输入)的值 - -不一定是一个字符串
  • 参数的值 - 这可以有一个默认值,或完全省略

例如,在过滤器{{var | foo:“bar”}}中,过滤器foo将传递变量var和参数“bar”

自定义filter代码文件摆放位置:

app01/
    __init__.py
    models.py
    templatetags/  # 在app01下面新建一个package package
        __init__.py
        app01_filters.py  # 建一个存放自定义filter的文件
    views.py

编写自定义filter:

from django import template
register = template.Library()


@register.filter(name="cut")
def cut(value, arg):
    return value.replace(arg, "")


@register.filter(name="addSB")
def add_sb(value):
    return "{} SB".format(value)

使用自定义filter:

{# 先导入我们自定义filter那个文件 #}
{% load app01_filters %}

{# 使用我们自定义的filter #}
{{ somevariable|cut:"0" }}
{{ d.name|addSB }}

 

四、模板语法之tags(与逻辑相关的)

1.for

语法:

①for循环的基本用法:
{% for i in name_list %}
{{ i }}
{% endfor %}

{% for i in name_list %}
{{ i }}
{% empty %}
空空如也
{% endfor %}


②for循环可用的属性:

forloop代表当前的for循环
forloop.counter    forloop.counter表示当前循环的执行次数的整数计数器。该计数器从1开始,即第一次循环时{{% forloop.counter %}}的值为1

forloop.counter0  forloop.counter0 计数从0开始,第一次循环其值为0

forloop.revcounter    值是一个整数,表示循环中剩余的元素数量。第一次循环时, for-loop.revcounter 的值是序列中要遍历的元素总数。最后一次循环时, forloop.revcounter 的值为 1 

forloop.revcounter0  索引是基于零的。第一次循环时, for-loop.revcounter0 的值是序列中元素数量减去一。最后一次循环时, forloop.revcounter0 的值为 0 

forloop.first     是个bool值,第一次循环时为true
forloop.last     是个bool值,最后一次循环时为true
forloop.parentloop    forloop.parentloop 引用父级循环的 forloop 对象

举例:

{% for country in countries %}
<table>
{% for city in country.city_list %}
<tr>
<td>Country #{{ forloop.parentloop.counter }}</td>
<td>City #{{ forloop.counter }}</td>
<td>{{ city }}</td>
</tr>
{% endfor %}
</table>

{% endfor %}

③for...empty...

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>

2.if,elif,else

语法:

{% if a > b %}
{% endif %}

{% if a > b %}
{% else %}
{% endif %}

{% if a > b %}
{% elif %}
{% else %}
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。

3.with

定义一个中间变量

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

自定义tags

自定义tags代码文件摆放位置:

编写自定义tags:

使用自定义tags:

 

小技巧:

static引入

注意:

①filter可以用在if等语句后,simple_tag不可以

{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

②注意事项

Django的模板语言不支持连续判断,即不支持以下写法:

{% if a > b > c %}
...
{% endif %}

③Django的模板语言中属性的优先级大于方法

def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})

如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的 d.items() 方法,此时在模板语言中:

{{ data.items }}

默认会取d的items key的值。

五、模板之母版继承之block与extends

为什么要有母版(why):

 可以将每个页面共有的部分定义为母版使用,多个页面公用的部分提取出来,放在一个 母版 里面,其他的页面只需要 继承 母版就可以了。

1.具体使用的步骤:
① 把公用的HTML部分提取出来,放到base.html文件中
②在base.html中,通过定义block,把每个页面不同的部分区分出来

{% block page-main %}
...
{% endblock%}


③在具体的页面中,先继承母版

{% extends 'xxx.html' %}

④然后block名去指定替换母版中相应的位置

2.母版的继承

 在子页面中在页面最上方使用下面的语法来继承母板。

{% extends 'layouts.html' %}

3.母版的导入

语法:{% include '模版名称' %}

 如:{% include 'adv.html' %}

使用母版继承的注意事项:

①{% extends 'base.html' %} --> 母版文件:base.html要加引号
②{% extends 'base.html' %}必须放在子页面的第一行!!!
③可以在base.html中定义很多block,通常我们会额外定义page-css和page-js两个块
④view.py相应的函数中返回的是对应的子页面文件不是base.html

④view.py相应的函数中返回的是对应的子页面文件不是base.html

④view.py相应的函数中返回的是对应的子页面文件不是base.html

重要的事情说三遍

静态文件相关:

用法一:{% static "xxx.css" %}

引用图片

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

引入Js

{% load static %}
<script src="{% static "mytest.js" %}"></script>

某个文件多处被用到可以存为一个变量

% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

用法二 :使用get_static_prefix

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />
{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

六、模板之母版导入之include(组件)

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

{% include 'navbar.html' %}

七、自定义simpletag

①先去setting里面把app名字配置上
②再app目录下创建一个templatetags模块
③写py文件(my_test.py)

from django import template
register=template.Library()
@register.inclusion_tag('test.html')
def my_inclusion(n):
  data=[]
  for i in range(n):
  data.append('第%s行'%i)
  return {'data':data}

④写test.html页面

<ul>
{% for choice in data %}
<li>{{ choice }}</li>
{% endfor %}
</ul>

⑤{% load my_test %}
⑥{% my_inclusion 10 %} 它会返回html的页面

inclusion_tag

多用于返回html代码片段

示例:

templatetags/my_inclusion.py

from django import template

register = template.Library()


@register.inclusion_tag('result.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}项".format(i) for i in range(1, n+1)]
    return {"data": data}
View Code

templates/snippets/result.html

<!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>inclusion_tag test</title>
</head>
<body>

{% load inclusion_tag_test %}

{% show_results 10 %}
</body>
</html>
View Code
原文地址:https://www.cnblogs.com/neymargoal/p/9599749.html