django入门教程之templates和static资源【五】
使用app01子应用举例说明模板的使用。templates官方文档。
templates完整流程认知
第一步,在settings.py中注册app01子应用。

第二步,在app01目录下,新建templates和static目录,用于存放模板文件和资源文件。目录结构如下:

# user_list.html文件内容
<!DOCTYPE html>
{% load static %}<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="{% static 'plugins' %}">
</head>
<body><p>姓名是{{name}}, 性别是{{sex}}</p><p>身高是{{height}}, 体重是{{weight}}</p><h1>DTL模板引擎</h1><img src="/static/img/1.jpg" alt="">
</body>
</html>
第三步,在 app01/views.py中编写代码。注意render里的context字段值,和html文件中的变量名是对应关系。
# app01/views.pyfrom django.shortcuts import render # 返回htmldef user_list(request):# 按settings.py中app的注册顺序依次寻找templates目录# data = {"name": "testyan", "sex": "M"}height = 190weight = 200# return render(request, template_name='user_list.html', context=data)# locals()用于获取本地变量return render(request, template_name='user_list.html', context=locals())# app01/urls.py
from django.urls import pathfrom . import viewsurlpatterns = [path('index/', views.index),path('user/list', views.user_list)
]
第四步,通过浏览器访问。

第二步中templates目录也可以建在根目录下,但要在settings.py中注册模板路径:
同样,static目录也可以建在根目录下,但要在settings.py中注册static资源路径:
django中的static下的静态资源,可以直接通过http://127.0.0.1:1992/static/xxxx拼接地址访问。但项目上线以后,关闭debug模式时,django默认是不提供静态文件的访问支持,项目部署的时候,我们会通过收集静态文件使用nginx这种web服务器来提供静态文件的访问支持。
代码缓存优化
上述的代码,我们可以进行缓存优化,即是将访问过的html保存到cache中,下次访问就不需要重新render渲染,而是直接从cache中读取。先在app01目录下新建.cache目录。
app01/views.py文件代码:
def user_list(request):height = 190weight = 200# return render(request, template_name='user_list.html', context=locals())if os.path.exists(BASE_DIR/'app01/.cache'/'user_list.html'):print('走缓存文件')with open(BASE_DIR / 'app01/.cache' / 'user_list.html', 'r') as f:content = f.read()else:print('没走缓存文件')# content = render_to_string('user_list.html', context=locals())# 以下两行代码等同于上一行代码template = get_template('user_list.html')content = template.render(locals(), request)with open(BASE_DIR/'app01/.cache'/'user_list.html', 'w') as f:f.write(content)return HttpResponse(content)
通过浏览器访问http://127.0.0.1:1992/app01/user/list时,只有第一次访问会打印“没走缓存文件”,后续访问都打印“走缓存文件”。
模板引擎语法
上述其实已经用到了变量的基础语法,格式为:{{变量}}
变量
在app01/urls.py中绑定路由不再截图示例。后续都不再强调这些步骤,默认实现。
以下是对列表、元组、集合、字典、对象等在模板引擎中的使用方式。
# app01/views.py
def index2(request):list_var = ['v', 'vv', 'vvv']tuple_var = ('ty', 100)set_var = {'small', 'big'}dict_var = {'ishappy': 'yes'}obj_var = osreturn render(request, template_name='user_list.html', context=locals())
<!DOCTYPE html>
{% load static %}<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="{% static 'plugins' %}">
</head>
<body>
<!-- <p>姓名是{{name}}, 性别是{{sex}}</p>-->
<!-- <p>身高是{{height}}, 体重是{{weight}}</p>--><h1>DTL模板引擎</h1>
<!-- <img src="/static/img/1.jpg" alt="">-->
<!-- <h1>html默认注释</h1>-->{# DTL单行注释 #}{% comment %}多行注释多行注释{% endcomment %}{# DTL中列表和元组,通过下标取值;而集合,通过pop取值,当集合都被清空后会报错 #}<p>列表变量={{list_var}}, 列表单个元素={{list_var.1}}</p><p>元组变量={{tuple_var}}, 元组单个元素={{tuple_var.0}}</p><p>集合变量={{set_var}}, 集合单个元素={{set_var.pop}}, {{set_var.pop}}</p><p>字典变量={{dict_var}}, 字典单个元素={{dict_var.ishappy}}</p><p>对象变量={{obj_var}}, 对象中的方法调用返回的内容={{obj_var.getcwd}}</p></body>
</html>

标签
当数据过于复杂时,需要用到条件判断或循环功能。DTL中的 if 和 for 用法如下:
# views.py#coding=utf-8
import osfrom django.http import HttpResponse # 返回文字
from django.shortcuts import render # 返回htmldef index2(request, idd):id_var = iddfruit_list = [{"id": 1, "name": "苹果", "price": 10},{"id": 2, "name": "香蕉", "price": 2.9},{"id": 3, "name": "菠萝", "price": 9.9}]return render(request, template_name='user_list.html', context=locals())
<!DOCTYPE html>
{% load static %}<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="{% static 'plugins' %}">
</head>
<body>{% if id_var == 0 %}<p>id=0</p>{% elif id_var <= 10 %}<p>id是1-10以内</p>{% elif id_var > 10 and id_var <= 100 %}<p>id是11-100以内</p>{% else %}<p>id大于100</p>{% endif %}{% for fruit in fruit_list %}<p>第{{forloop.counter}}行,{{fruit.name}}的价格是{{fruit.price}}</p>{% endfor %}</body>
</html>

for循环中提供了forloop对象:
| 属性 | 描述 |
| forloop.counter | 显示循环的次数,从1开始 |
| forloop.counter0 | 显示循环的次数,从0开始 |
| forloop.revcounter0 | 倒数显示循环的次数,从0开始 |
| forloop.revcounter | 倒数显示循环的次数,从1开始 |
| forloop.first | 判断如果本次是循环的第一次,则结果为True |
| forloop.last | 判断如果本次是循环的最后一次,则结果为True |
| forloop.parentloop | 在多层嵌套循环中,指向当前循环的上级循环对象 |
过滤器
内置过滤器
全部内置过滤器请参考:过滤器官方文档,以下只列出一些比较常用的:
【过滤器用法都是{{str|default:"默认值”}} ,没有像python中default()这种用法】
| 内置过滤器 | 用法 | 示例 |
| last | 获取列表/元组的最后一个成员 | {{list | last}} |
| first | 获取列表/元组的第一个成员 | {{list|first}},也可以使用{list.0}} |
| length | 获取数据的长度 | {{list | length}} |
| default | 当变量没有值的情况下,系统输出默认值, | {{str|default:"默认值”}} |
| safe | 标记一个字符串在输出前不需要进一步的 HTML 转义。当自动转义关闭时,该过滤器没有效果。 | {{htmlcontent| safe}} |
| date | 日期时间格式转换 | {{ value| date:"Y-m-d H:i:s" }} |
| cut | 从内容中截取掉同样字符的内容 | {{content | cut:"hello"}} |
| filesizeformat | 把文件大小的数值转换成单位表示 | {{filesize | filesizeformat}) |
| join | 用字符串连接一个列表,就像 Python 的 str.join(list) 一样。 | {{list| join:"-"}} |
| random | 随机提取某个成员 | {list | random}} |
| truncatechars | 按字符长度截取内容 | {{content | truncatechars:30}} |
# views.py中相关代码
def index2(request):list_var = ['v', 'vv', 'vvv']time = datetime.datetime.now()url = '<a href="https://www.qq.com">链接</a>'return render(request, template_name='user_list.html', context=locals())
# html文件相关代码 <p>列表中取随机元素={{list_var|random}}</p><p>当前时间={{time|date:'Y-m-d H:i:s'}}</p><p>不存在的字段名={{work|default:'no'}}</p><p>{{url|safe}}</p>
浏览器访问结果:
![]()
自定义过滤器
在上述for循环中,价格的小数位数是不一致的,我们可以通过自定义过滤器实现此功能。
前置操作:一定要把用到templates的app注册到settings.py的INSTALLED_APPS中。
根据官方文档,我们要在app01目录下,新建一个python包,名为 templatetags,注意这里新建的一定得是python包,而不能是普通的directory。
然后在templatetags目录下,新建一个python文件,这个文件名需要在html文件中加载。

num_format.py代码:
from django import templateregister = template.Library()# @register.filter("df")
def data_format(content, form=1):return f'%.{form}f' % content# 用装饰器或者用这个
register.filter("df", data_format)
html相关代码:
{% for fruit in fruit_list %}<p>第{{forloop.counter}}行,{{fruit.name}}的价格是{{fruit.price|df:1}}</p>
{% endfor %}
重启!重启!

然后再通过浏览器访问时,就会发现price字段值都保留到小数点后一位,成功啦~~
模板分离和模板继承
模板分离
我们知道,不同路由页面一般都有些公共的内容,我们可以将公共的html代码提取出来,单独存入一个html,以便复用,这样叫做“模板分离”。
新建一个子应用sep,将应用注册模板,编写视图函数,配置路由等。将公共html内容写入public.html,而特定index1.html引用时,语法为
{% include 'public.html' %}

浏览器访问效果:
模板继承
继承语法:
{% extends 'base.html' %}
自定义块语法:
{% block 块名 %} xxxxx {% endblock %}

红框内容解析:在base.html中写入通用的html代码,特有的模块使用block来编写,然后在auth.html和account.html中对block具体实现。
绿框内容解析:在base.html中也可以写入block块的默认实现,auth.html中想去除“关闭浏览器”的功能,就重写block,中间为空或改为其它内容。

相关文章:
django入门教程之templates和static资源【五】
使用app01子应用举例说明模板的使用。templates官方文档。 templates完整流程认知 第一步,在settings.py中注册app01子应用。 第二步,在app01目录下,新建templates和static目录,用于存放模板文件和资源文件。目录结构如下&#…...
Vue 中directive的钩子函数(bind、inserted 等)的作用及使用场景
大白话Vue 中directive的钩子函数(bind、inserted 等)的作用及使用场景。 在 Vue 里,指令(directive)是个超实用的东西,它能让你在不改动组件逻辑的情况下,给 HTML 元素添加一些特殊的行为。Vu…...
【区块链安全 | 第一篇】密码学原理
文章目录 1.哈希函数1.1 哈希函数的性质1.2 常见哈希算法1.3 Merkle Tree(默克尔树)1.4 HMAC(哈希消息认证码) 2. 公钥密码学2.1 对称加密 vs 非对称加密2.2 RSA 算法2.3 ECC(椭圆曲线密码学)2.4 Diffie-He…...
Linux安装MySQL数据库并使用C语言进行数据库开发
目录 一、前言 二、安装VMware运行Ubuntu 1.安装VMware 2.使用VMware打开Ubuntu 三、配置VMware使用网卡 1.添加NAT网卡 四、Linux下安装MySQL数据库 五、安装MySQL开发库 六、演示代码 sql_connect.c sql_connect.h main.c中数据库相关代码 结尾 一、前言 由于最…...
2024年MathorCup数学建模A题移动通信网络中PCI规划问题解题全过程文档加程序
2024年第十四届MathorCup高校数学建模挑战赛 A题 移动通信网络中PCI规划问题 原题再现: 物理小区识别码(PCI)规划是移动通信网络中下行链路层上,对各覆盖小区编号进行合理配置,以避免PCI冲突、PCI混淆以及PCI模3干扰等现象。PCI规划对于减少…...
伯努利分布和二项分布学习笔记
目录 1. 伯努利分布1.1定义1.2概率质量函数1.3数学期望与方差1.4应用示例 2. 二项分布2.1定义2.1概率质量函数2.2数学期望与方差2.3性质与图形 3. 伯努利分布与二项分布的关系4. 总结 1. 伯努利分布 伯努利分布(Bernoulli Distribution),又称…...
Redis实战常用二、缓存的使用
一、什么是缓存 在实际开发中,系统需要"避震器",防止过高的数据访问猛冲系统,导致其操作线程无法及时处理信息而瘫痪. 这在实际开发中对企业讲,对产品口碑,用户评价都是致命的。所以企业非常重视缓存技术; 缓存(Cache):就是数据交换的缓冲区&…...
G口服务器和普通服务器之间的区别
今天小编主要来为大家介绍一下G口服务器和普通服务器之间的区别! 首先,从硬件配置上看,普通服务器通常都会配备中央处理器、内存和硬盘等基本的硬件配置,能够适用于各种应用程序和服务;G口服务器除了基础的硬件配置还增…...
通过国内源在Ubuntu20.0.4安装repo
国内三大免费源: 清华大学:清华大学开源软件镜像站 | Tsinghua Open Source Mirror中国科技大学:USTC Open Source Software Mirror阿里云:阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 repo只在清华源网站里搜到:…...
多维动态规划 力扣hot100热门面试算法题 面试基础 核心思路 背题
多维动态规划 不同路径 https://leetcode.cn/problems/unique-paths/ 核心思路 比较简单 f[i][j] f[i - 1][j] f[i][j - 1] ; 示例代码 class Solution {public int uniquePaths(int n, int m) {int[][] f new int[n][m];for (int i 0; i < n; i)f[i][0] 1;for…...
《Java到Go的平滑转型指南》
文章目录 **文章摘要****核心主题****关键内容提炼****决策者行动清单****核心结论** **第一章:转型决策:为什么要从Java转向Go?****1.1 性能对比:GC机制与并发模型差异****GC机制对比****并发模型基准测试** **1.2 开发效率&…...
【软件测试】:软件测试实战
1. ⾃动化实施步骤 1.1 编写web测试⽤例 1.2 ⾃动化测试脚本开发 common public class AutotestUtils {public static EdgeDriver driver;// 创建驱动对象public static EdgeDriver createDriver(){// 驱动对象已经创建好了 / 没有创建if( driver null){driver new EdgeDr…...
SpringMVC 请求处理
SpringMVC 请求处理深度解析:从原理到企业级应用实践 一、架构演进与核心组件协同 1.1 从传统Servlet到前端控制器模式 SpringMVC采用前端控制器架构模式,通过DispatcherServlet统一处理请求,相比传统Servlet的分散处理方式,实…...
unittest自动化测试实战
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 为什么要学习unittest 按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程…...
leetcode3.无重复字符的最长字串
采用滑动窗口方法 class Solution { public:int lengthOfLongestSubstring(string s) {int ns.size();if(n0)return 0;int result0;unordered_set<char> set;set.insert(s[0]);for(int i0,j0;i<n;i){while(j1<n&&set.find(s[j1])set.end()){set.insert(s[…...
Android Compose 框架派生状态(derivedStateOf、rememberCoroutineScope)深入剖析(十五)
一、引言 在 Android 开发领域,高效的状态管理对于构建响应式、高性能的应用程序至关重要,在 Jetpack Compose 中,derivedStateOf 和 rememberCoroutineScope 这两个与派生状态相关的特性在状态管理方面发挥着关键作用。派生状态允许我们根据…...
3.25-2request库
request库 一、介绍request库 (1)requests是用python语言编写的简单易用的http库,用来做接口测试的库; (2)接口测试自动化库有哪些? requests、urllib 、urllib2、urllib3、 httplib 等&…...
《破解老龄化的智能密钥:机器人四维战略与未来养老生态》
一、引言:老龄化社会与智能机器人的必然性 全球老龄化趋势与老年人核心需求(健康管理、生活辅助、心理陪伴、安全保障) 全球正面临着严峻的老龄化挑战。根据联合国发布的数据,全球60岁及以上人口数量在过去几十年中持续增长&…...
Docker-Volume数据卷详讲
Docker数据卷-Volume 一:Volume是什么,用来做什么的 当删除docker容器时,容器内部的文件就会跟随容器所销毁,在生产环境中我们需要将数据持久化保存,就催生了将容器内部的数据保存在宿主机的需求,volume …...
SpringMVC 配置
一、MVC 模式简介 在软件开发的广袤天地中,MVC 模式宛如一座明亮的灯塔,指引着开发者构建高效、可维护的应用程序。Spring MVC 作为基于 Spring 框架的重要 web 开发模块,更是将 MVC 模式的优势发挥得淋漓尽致,堪称 Servlet 的强…...
Python 3.8 Requests 爬虫教程(2025最新版)
遵守网站的爬虫规则、避免爬取敏感信息、保护个人隐私! 一、环境配置与基础验证 # 验证 Python 版本(需 ≥3.8) import sys print(sys.version) # 应输出类似 3.8.12 的信息# 安装 requests 库(若未安装) # 命令行执…...
蓝桥杯备考之 最长上升子序列问题(挖地雷)
这道题其实就是正常的最长上升子序列问题,但是我们还要把最优方案输出出来,我们可以用个pre数组来维护就行了,每当我们更新以i为结尾的最长子序列,如果i是接在1到i-1某个点后面的话就把前面的点存到pre里面 最后我们把pre倒着打印…...
华为OD机试2025A卷 - 游戏分组/王者荣耀(Java Python JS C++ C )
最新华为OD机试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 题目描述 2020年题: 英雄联盟是一款十分火热的对战类游戏。每一场对战有10位玩家参与,分为两组,每组5人。每位玩家都有一个战斗力,代表着这位玩家的厉害程度。为了对战尽可能精彩,我们需要…...
【Python Cookbook】字符串和文本(二)
字符串和文本(二) 6.字符串忽略大小写的搜索替换7.最短匹配模式8.多行匹配模式9.将 Unicode 文本标准化10.在正则式中使用 Unicode 6.字符串忽略大小写的搜索替换 你需要以忽略大小写的方式搜索与替换文本字符串。 为了在文本操作时忽略大小写…...
Redisson 实现分布式锁简单解析
目录 Redisson 实现分布式锁业务方法:加锁逻辑LockUtil 工具类锁余额方法:工具类代码枚举代码 RedisUtil 工具类tryLock 方法及重载【分布式锁具体实现】Supplier 函数式接口调用分析 Redisson 实现分布式锁 业务方法: 如图,简单…...
六十天Linux从0到项目搭建(第五天)(file、bash 和 shell 的区别、目录权限、默认权限umask、粘滞位、使用系统自带的包管理工具)
1. file [选项] 文件名 用于确定文件类型的实用工具。它会通过分析文件内容(而不仅仅是文件扩展名)来判断文件的实际类型 示例输出解析 $ file /bin/bash /bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, i…...
信源的分类及数学模型
信源的分类及数学模型 按照信源发出的时间和消息分布分为离散信源和连续信源 按照信源发出符号之间的关系分为无记忆信源和有记忆信源 单符号离散信源(一维离散信源) 信源输出的消息数有限或可数,且每次只输出符号集的一个消息 样本空间&…...
嵌入式硬件工程师从小白到入门-PCB绘制(二)
PCB绘制从小白到入门:知识点速通与面试指南 一、PCB设计核心流程 需求分析 明确电路功能(如电源、信号处理、通信)。确定关键参数(电压、电流、频率、接口类型)。 原理图设计 元器件选型:匹配封装、电压、…...
抽象工厂设计模式及应用案例
引言 在软件开发中,合理的设计模式可以有效地提高代码的可维护性、可扩展性和可重用性。抽象工厂模式(Abstract Factory Pattern)便是一个重要的创建型设计模式,它允许我们在不指定具体类的情况下,创建一系列相关或相…...
LVS NAT模式实现三台RS的轮询访问
节点规划: 配置RS: RS1-RS3的网关配置均为 192.168.163.8 配置RS1: [rootlocalhost ~]# hostnamectl hostname rs1 [rootlocalhost ~]# nmcli c modify ens160 ipv4.method manual ipv4.addresses 192.168.163.7/24 ipv4.gateway 192.168.163.8 conne…...



