Django学习纪录 7.模板的变量与标籤[附常用的过滤器整理]

之前有在用Django写一些小网站,现在暑假想说再来複习一下之前买的这本书
http://img2.58codes.com/2024/20118889bj9fH1vhuR.jpg
于是我就把它写成一系列的文章,也方便查语法
而且因为这本书大概是2014年出的,如今Django也已经出到2.多版
有些内容也变得不再支援或适用,而且语法或许也改变了
所以我会以最新版的Python和Django来修正这本书的内容跟程式码

目录:django系列文章-Django学习纪录

7. 模板的变量与标籤

7.1 变量进阶

从这里开始我们将以一个新的範例来做说明
请新建一个根目录名称为demo的虚拟环境
demo/mysite/mysite/urls.py

from django.contrib import adminfrom django.urls import pathfrom mysite.views import menuurlpatterns = [    path('admin/', admin.site.urls),    path('menu/', menu),]

demo/mysite/mysite/views.py

from django.shortcuts import render_to_responsedef menu(request):    food = {'name': '番茄炒蛋', 'price': 60, 'comment': '好吃', 'is_spicy': False}    return render_to_response('menu.html', locals())

7.2 变量下层查找

demo/mysite/templates/menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        <ul>            <li> 食物的名字是: {{ food.name }}</li>            <li> 食物的价格是: {{ food.price }}</li>            <li> 食物说明: {{ food.comment }}</li>            <li> 食物会辣? {{ food.is_spicy }}</li>        </ul>    </body></html>

整理一下变量的
优先序 | 变量类型 | 範例 | 在Python中的对应 | 备注
------------- | -------------
1 | 字典 | {{food.name}} | food['name'] | 字典的键是整数时也通,如:{{food.1}}
2 | 属性 | {{food.bar}} | foo.bar | 在这里bar是foo的物件属性
3 | 方法 | {{food.bar}} | foo.bar() | 在这里bar是foo的物件方法
4 | 清单 | {{food.0}} | food[0] | 在这里foo是清单,譬如foo=['a','b','c']
这边django会依序查找第一个相符的项目后便结束查询
变量的写法若本身有误,会导致错误的页面
但是变量往下层若无法查找则会以该便量不显示的方式(即留白)回传正常页面
注意模板语言并不是python语言,所以请不要出现{{food['name']}}这种奇特的写法

7.3 标籤

7.3.1 for 标籤

views.py

from django.shortcuts import render_to_responsedef menu(request):    food1 = {'name': '番茄炒蛋', 'price': 60, 'comment': '好吃', 'is_spicy': False}    food2 = {'name': '蒜泥白肉', 'price': 100, 'comment': '人气推荐', 'is_spicy': True}    return render_to_response('menu.html', locals())

menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        <h3>第1道食物</h3>        <ul>            <li> 食物的名字是: {{ food1.name }}</li>            <li> 食物的价格是: {{ food1.price }}</li>            <li> 食物说明: {{ food1.comment }}</li>            <li> 食物会辣? {{ food1.is_spicy }}</li>        </ul>        <h3>第2道食物</h3>        <ul>            <li> 食物的名字是: {{ food2.name }}</li>            <li> 食物的价格是: {{ food2.price }}</li>            <li> 食物说明: {{ food2.comment }}</li>            <li> 食物会辣? {{ food2.is_spicy }}</li>        </ul>    </body></html>

如果这里有超级多笔资料不就惨了?
所以我们要介绍for标籤
views.py

from django.shortcuts import render_to_responsedef menu(request):    food1 = {'name': '番茄炒蛋', 'price': 60, 'comment': '好吃', 'is_spicy': False}    food2 = {'name': '蒜泥白肉', 'price': 100, 'comment': '人气推荐', 'is_spicy': True}    foods = [food1, food2]    return render_to_response('menu.html', locals())

menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        {% for food in foods %}            <ul>                <li> 食物的名字是: {{ food.name }}</li>                <li> 食物的价格是: {{ food.price }}</li>                <li> 食物说明: {{ food.comment }}</li>                <li> 食物会辣? {{ food.is_spicy }}</li>            </ul>        {% endfor %}    </body></html>

output:
http://img2.58codes.com/2024/20118889FKggRh6jNq.png
成功让for帮我们迭代foods里的资料

forloop变量及其属性

接着要显示第n道食物的标题
menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        {% for food in foods %}            <h3>第{{ forloop.counter }}道食物</h3>            <ul>                <li> 食物的名字是: {{ food.name }}</li>                <li> 食物的价格是: {{ food.price }}</li>                <li> 食物说明: {{ food.comment }}</li>                <li> 食物会辣? {{ food.is_spicy }}</li>            </ul>        {% endfor %}    </body></html>

output:
http://img2.58codes.com/2024/201188894bZwd2e5z9.png
整理一下各种用法

forloop属性说明forloop.counter计数器,由1开始递增到迭代总数forloop.counter0计数器,由0开始递增到迭代总数forloop.revcounter倒数器,由迭代总数递减到1forloop.revcounter0倒数器,由迭代总数递减到0forloop.first若是第一次for迴圈,则为真,否则为假forloop.last若是最后一次for迴圈,则为真,否则为假forloop.parentloop父迴圈(上一层迴圈)的forloop变量for标籤允许巢状结构,但是如果要取用上一层的forloop变量则要使用forloop.parentloop来取得

选用的empty标籤

如果forloop所要迭代的元素量为0时
则改为输出本区块的内容
menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        {% for food in foods %}            <h3>第{{ forloop.counter }}道食物</h3>            <ul>                <li> 食物的名字是: {{ food.name }}</li>                <li> 食物的价格是: {{ food.price }}</li>                <li> 食物说明: {{ food.comment }}</li>                <li> 食物会辣? {{ food.is_spicy }}</li>            </ul>        {% empty %}            <p>本餐厅啥都没卖!</p>        {% endfor %}    </body></html>

倒转元素

如果想要反向输出的话,有两种方式

在视图函式中使用清单的reverse()方法将for标籤改为
{% for food in foods reversed %}

for标籤的限制

如果要同时迭代字典的键与值
必须这样做

{% for key, value in items %}    {{ key }} = {{ value }}{% endfor %}}

{% for item in items %}    {{ item.0 }} = {{ item.1 }}{% endfor %}}

内建函式items()将字典的键与值分别抽出成为元组
举例,在正常的python程式中

dic1 = {'a': 1,'b': 2}dic2 = dic1.items()print(dic2)

output:

dict_items([('a', 1), ('b', 2)])

7.3.2 if/elif/else 标籤

在django模板中使用if判断式
menu.html

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        {% for food in foods %}            <h3>第{{ forloop.counter }}道食物</h3>            <ul>                <li> 食物的名字是: {{ food.name }}</li>                <li> 食物的价格是: {{ food.price }}</li>                <li> 食物说明: {{ food.comment }}</li>                <li> 食物会辣? {% if food.is_spicy %} 辣 {% else %} 不辣 {% endif %}</li>            </ul>        {% empty %}            <p>本餐厅啥都没卖!</p>        {% endfor %}    </body></html>

也可以用elif
举例

{% if food.is_sour %}    酸{% elif food.is_sweet %}    甜{% elif food.is_bitter %}    苦{% elif food.is_spicy %}    辣{% else %}    没味道{% endif %}

7.3.3 注解与注解标籤

一行的注解

{# this is comment #}多行的注解{% comment %}多行注解{% endcomment %}

7.4 过滤器

过滤器(filter)搭配变量一起使用,利用|管道符号(pipe)可以获取变量的资讯
如果想要显示项目的数量(或长度)

<!DOCTYPE html><html>    <head>        <title> Menu </title>        <meta charset="UTF-8">    </head>    <body>        <p>本餐厅共有 {{ foods|length }} 道菜</p>        {% for food in foods %}            <h3>第{{ forloop.counter }}道食物</h3>            <ul>                <li> 食物的名字是: {{ food.name }}</li>                <li> 食物的价格是: {{ food.price }}</li>                <li> 食物说明: {{ food.comment }}</li>                <li> 食物会辣? {% if food.is_spicy %} 辣 {% else %} 不辣 {% endif %}</li>            </ul>        {% empty %}            <p>本餐厅啥都没卖!</p>        {% endfor %}    </body></html>

过滤器也允许串连的形式,例如
{{ restaurants|first|length }}
这将会列出第一家餐厅的菜单数目
{{ word|truncatewords:"30" }}
会输出word变量的前30个字

整理一下常用的过滤器(出自 文渊阁python架站特训班django最强实战 书籍p.3-18)
过滤器名称 | 範例 | 说明
------------- | -------------
add | {{ value|add:"2" }} | 如果value=4,输出结果6,如果value="A",输出结果A2
addslashes | {{ value|addslashes }} | 如果value="I don\'t know",输出结果I don\'t know
capfirst | {{ value|capfirst }} | 将value字串第一个字元转为大写,若字元不是字母就不处理
cut | {{ value|cut:"指定字串" }} | 移除value字串中所有指定的字串
date | {{ value|date:"D d M Y" }} | 假如为2019年7月15日15:16,显示结果为 星期一 15 七月 2019
default | {{ value|default:"预设值" }} | 如果value是空字串,将输出预设值
dictsort | {{ value|dictsort:"键" }} | 将字典依指定的键递增排序
dictsortreversed | {{ value|dictsortreversed:"键" }} | 将字典依指定的键递减排序
divisibleby | {{ value|divisibleby:"3" }} | 若value可被3整除,传回True
escape | {{ value|escape }} | 若value中含有html标籤,html标籤将会失去作用,被视为文字输出
filesizeformat | {{ value|filesizeformat }} | 转成档案大小,若value=123456789,结果为117.7MB
first | {{ value|first }} | 传回value串列中第一个项目
join | {{ value|join:" // " }} | 将串列元素以指定字元串接,例如value=['a','b',c'],结果为a // b // c
last | {{ value|last }} | 传回value串列中最后一个项目
length | {{ value|length }} | 传回value串列或字串的长度,若变数未定义则传回0
length_is | {{ value|length_is:"4" }} | 若value长度为4,传回True
linebreaks | {{ value|linebreaks }} | 将文字内容的换行符号\n转换为html的<br/><p></p>,例如value="I\nlove you",结果<p>I<br/>love you</p>
linebreaksbr | {{ value|linebreaksbr }} | 将文字内容的换行符号\n转换为html的<br/>,例如value="I\nlove you",结果I<br/>love you
linenumbers | {{ value|linenumbers }} | 在文字前面加上行号,例如value="I\nlove you",结果1. I 2. love you
lower | {{ value|lower }} | 将字串转换为小写
upper | {{ value|upper }} | 将字串转换为大写
make_list | {{ value|make_list }} | 将字串转换为串列,例如value="123",结果['1','2','3']
random | {{ value|random }} | 以乱数方式取得串列元素
safe | {{ value|safe }} | 以html格式读取字串
slice | {{ value|slice:":2" }} | 传回部分字串或串列,同[:2]
slugify | {{ value|slugify }} | 将字串中的空白以-取代
stringformat | {{ value|stringformat }} | 以科学记号表示,例如value=4,结果4.000000E+00
title | {{ value|title }} | value="my FIRST post",结果My First Post
truncatechars | {{ value|truncatechars:9 }} | value="Joel is a slug",结果Joel i...
wordcount | {{ value|wordcount }} | 传回单词数目
yesno | {{ value|yesno:"是,否,取消" }} | 依value是True False None分别显示是、否、取消

上一篇:Django学习纪录 6.模板初探

下一篇:Django学习纪录 8.模型与资料库


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章