Django之模版层

文章目录

模版语法传值

python 复制代码
	模板层三种语法
	{{}}:主要与数据值相关
	{%%}:主要与逻辑相关
	{##}:模板注释

django的模板语法是自己写的 跟jinja2不一样
'''
1.针对需要加括号调用的名字 django模板语法会自动加括号调用你只需要写名字就行
2.模板语法的注释前端浏览器是无法查看的 {##},
模板语法{##}是由后端处理的,当识别为模板注释时就会从html文件中移除了,不会返回给用户;
而html注释<!---->是由前端浏览器对html处理时渲染时不做处理,但检查网页源码时还是能看见这些注释的。
'''

通过之前的Django知识的了解,如果我们需要向页面传递参数,可以通过render函数帮助我们实现:

第一种方式:手动将所有内容放入字典内进行传递

python 复制代码
	def index(request):
	    name = 'jack'
	    dic = {'hobby':['jump','music','rap']}
	    return render(request,'index.html', {'name': name, 'dic': dic})

第一种方式传值:精准传值 不浪费资源 针对多资源的传递书写麻烦

第二种方式:将当前名称空间中所有的变量名与值全部传递

python 复制代码
	def index(request):
	    name = 'jack'
	    dic = {'hobby': ['jump', 'music', 'rap']}
	    return render(request,'index.html',locals())

第二种方式传值:将函数名称空间中所有的名字全部传递 名字过多并且不使用的情况下比较浪费资源

模版语法传值特性

python 复制代码
		1.关于模版语法传值的范围是很大的 我们的八大数据类型都可以传值还有函数以及类
		2.文件对象也可以展示并调用方法
		3.函数名的传递会自动加括号执行并将返回值展示到页面上 需要写上return返回值才可以返回到页面
			注意函数如果有参数则不会执行也不会展示 模板语法不支持有参函数
			
		4.类名的传递也会自动加括号产生对象内存地址并展示到页面上
			如果想使用的话可以通过对象句点符的方式点出来

		5.对象不会加括号,但可以获取对象的一些数据属性
		6.索引、键、属性只能通过句点的方式取
		
		ps:总结针对可以加括号调用的名字模板语法都会自动加括号调用
		ps:模板语法会判断每一个名字是否可调用 如果可以则调用!!!

模版语法标签

在模板内通过:{% %} 来定义;例如:{%for %} {% endfor %}。在前面Django学习的章节内我们就使用了:

python 复制代码
	{% load static %} # 加载静态接口
	{% static '静态文件路径' % # 使用静态接口作为前缀寻找静态文件
	{% url '路由别名' %} # 根据路由别名执行该路由规则
	{% for obj in data %} # 给定一个迭代器,根据其内容决定遍历次数
		代码块
	{% endfor %}

语法格式

python 复制代码
	if elif else
		{% if 条件 %}  条件一般是模板语法传过来的数据  直接写名字使用即可
	        条件成立执行的代码
	    {% elif 条件1 %}
	 		  条件1成立执行的代码	
	    {% else %}
	       	 条件都不成立执行的代码
	    {% endif %}
		    
	for循环(html页面输入for Tab后面会自动补全)需要用到一个关键字 forloop 用来记录循环第几次的
		{% for i in str %}
		    {% if forloop.first %}
		        <p>这是我循环第一次!!</p>
		    {% elif forloop.last %}
		        <p>这是我最后一次循环!!</p>
		    {% else %}
		        <p>{{ i }}</p>
		    {% endif %}
		    {% empty %}
		        <p>我是判断当前标签是否有值的哦! 如果是空我就运行啦!!</p>
		{% endfor %}

if模板标签

if这种模板标签非常类似于Python内的if,只不过部分模板标签都会有一个end标签名为作用域的结束,而Python则是以缩进为作用域。

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        <url>
            {% if 1 > 2 %}
                条件1>2判断成功执行
            {% elif 3 > 1 %}
                条件3>1判断成功执行
            {% elif 5 > 2 %}
                条件5>2判断成功执行
            {% else %}
                以上条件都没有触发
            {% endif %}
        </url>
      </body>
</html>

一个作用域内只有一个条件能执行成功,浏览器打开效果:

for模板标签

for标签的几个常用属性

for内可用 描述
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

视图传递一个列表,index.html:

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        <url>
            {% for li in lis %}
                {% if forloop.first %}
                    <li>我是第一个列表{{ li }}</li>
                {% elif forloop.last %}
                     <li>我是最后一个列表{{ li }}</li>
                 {% else %}
                    <li>{{ li }}</li>
                {% endif %}
            {% endfor %}
        </url>
      </body>
</html>

直接遍历forloop也是可以的,而它显示的则是上面提到的所有属性内容:

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        <url>
            {% for foo in lis %}
                {{ forloop }}
                <br/>
            {% endfor %}

        </url>
      </body>
</html>

补充:当for接收的值不存在,如何处理

如果给定迭代器为空或找不到,则for标记可以带有一个可选子句,其文本将显示:{% empty %}

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        <url>
            {% for foo in llllll %}
                {{ foo }}

                {% empty %}
                    该循环找不到遍历内容
            {% endfor %}

        </url>
      </body>
</html>

遍历一个字典:

python 复制代码
	
	{% for key,val in dic.items %}
	    <p>{{ key }}:{{ val }}</p>
	{% endfor %}
	
	{% for foo in d.keys %}
	    <p>{{ foo }}</p>
	{% endfor %}
	
	{% for foo in d.values %}
	    <p>{{ foo }}</p>
	{% endfor %}
	
	{% for foo in d.items %}
	    <p>{{ foo }}</p>
	{% endfor %}

with起别名

使用一个简单地名字缓存一个复杂的变量,当你需要使用一个"昂贵的"方法(比如访问数据库)很多次的时候是非常有用的

python 复制代码
	d = {'username':'kevin','age':18,'info':'这个人有点意思','hobby':[111,222,333,{'info':'NB'}]}

	# with起别名
	{% with d.hobby.3.info as nb  %}
	    <p>{{ nb }}</p>
	    在with语法内就可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式
	    <p>{{ d.hobby.3.info }}</p>
	{% endwith %}
	
	
	{% with total=business.employees.count %}
	    {{ total }} employee{{ total|pluralize }}
	{% endwith %}
	不要写成as

模版语法过滤器

该模板语法类似与Python的内置方法,通过|符号对值进行操作。

常用过滤器

语法:{{ value|过滤器名:参数 }}

过滤器用管道符隔开(无空格),最多支持多传入一个参数。

过滤器是支持链式的,可以将多个过滤器串起来,上一个过滤器的输出作为下一个的输入

过滤器 功能 示例
default 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。 {{ value|default:"nothing"}}
length 对于字符串列表这类有length属性的,得到其值 {{ value|length}}
filesizeformat 将传入的数字当做文件的字节数,将其处理成合适展示的文件大小,如2048就会展示为2 KB {{ value|filesizeformat }}
slice 对字符串进行切片 {{value|slice:"2:-1"}}
add 将传入的数字或字符串做相加或拼接处理 {{value|add:1}}
safe 模板语法默认转义带html语法的文本,safe取消标签文本转义,让其可以被html渲染 {{ value|safe}}
truncatechars 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列("...")结尾。 {{ value|truncatechars:9}}
truncatewords 在一定数量的字后截断字符串,处理同上...。 {{ value|truncatewords:9}}
cut 移除value中所有的与给出的变量相同的字符串如果value为'i love you',那么将输出'iloveyou'. {{ value|cut:' ' }}
timesince datetime数据距离现在的时间(从现在起) {{ blog_date|timesince }}
timeuntil datetime数据距离现在的时间(到现在止) {{ blog_date|timesince }}
date datetime数据字符化输出 {{ value|date:"Y-m-d H:i:s"}}

views.py

python 复制代码
	from django.shortcuts import render
	from datetime import datetime
	def index(request):
	    lis = [1,2,3,4,5]
	    num = 10
	    strs = 'Hello'
	    ctime = datetime.now()
	    b1 = True
	    b2 = False
	    file_size = 10502030
	    texts = '这是一段很长且内容丰富的文本'
	
	    return render(request, 'index.html', locals())

index.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        <p>获取值的长度:{{ lis|length }}</p>
        <p>加法运算:{{ num|add:20 }}</p>
        <p>字符串拼接:{{ strs|add:' World' }}</p>
        <p>日期格式:{{ ctime|date:'Y年-m月-d日 H时:i分:s秒' }}</p>
        <p>当结果为True:{{ b1|default:'我触发了' }}</p>
        <p>当结果不为True:{{ b2|default:'我触发了' }}</p>
        <p>通过数值计算文件大小:{{ file_size|filesizeformat }}</p>
        <p>截取文本(7位数,包含点):{{ texts|truncatechars:7 }}</p>
        <p>截取文本(3位数,包含点):{{ texts|truncatechars:3 }}</p>
      </body>
</html>

打开浏览器效果:


如果传入这种内容到前端会是什么样子呢;

python 复制代码
	h = "<h1>我是标题</h1>"

如果需要在后端就写好标签,传入到前端直接显示的话,存在两种方式:

方式一:导入一个新的方法来完成需求

python 复制代码
	from django.shortcuts import render
	from django.utils.safestring import mark_safe
	
	def index(request):
	    h = mark_safe("<h1>我是标题</h1>")
	
	    return render(request, 'index.html', locals())

方式二:后端正常传参,前端过滤解析

python 复制代码
	<!DOCTYPE html>
	<html lang="en">
	      <head>
	          <meta charset="UTF-8">
	          <title>index</title>
	      </head>
	      <body>
	        {{ h|safe }}
	      </body>
	</html>

自定义过滤器、标签、inclusion_tag

简介、环境准备

这类似于在Python内自定义函数,在开始前要做3个步骤:

  1. 在应用下创建一个名字必须叫"templatetags"文件夹
  2. 在上序文件夹内创建一个任意名称的py文件
  3. 在该py文件内固定先书写以下两条代码
python 复制代码
	from django import template
	register = template.Library()

完成上面步骤之后,记得重启Django项目啊!正式开始我们的实例


自定义过滤器

在定义的py文件内,开始创建我们的过滤器

python 复制代码
	@register.filter(name='myfileter') # 自定义过滤器
	def index(x,y): # 接受两个值
	    return x * y # 只做简单的运算

html文件首先要加载我们定义的过滤器,通过存放过滤器的那个py文件名

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>add</title>
      </head>
      <body>
        {% load mytag %} <!-- 加载自定义的过滤器 -->

        {{ 10|myfileter:2 }} <!-- 将10与2传进去了,进行10*2,得到20 -->
      </body>
</html>

页面打开效果

自定义标签

定义方式几乎与过滤器一致,我们这里定义的是简单版的标签

mytag.py

python 复制代码
	from django import template
	register = template.Library()
	
	# 自定义简单版标签(for那些标签都是通过register.tag定义出来的)
	@register.simple_tag(name='mysimple')
	def func1(a,b,c,d):
	    return '%s-%s %s:%s'%(a,b,c,d)

index.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        {% load mytag %}

        {% mysimple 1 'Hello' 2 'World' %}
      </body>
</html>

浏览器打开效果

自定义inclusion_tag

定义inclusion_tag是为了避免模块会重复代码
mytag.py

python 复制代码
	from django import template
	
	register = template.Library()
	
	# 自定义inclusion_tag
	@register.inclusion_tag('test.html', name='my_inclusion_tag')
	def func(n):
	    l = []
	    for i in range(1, n + 1):
	        l.append(f'第{i}页')
	
	    return {'lis':l} # 表示将列表传入到test.html页面内

test.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>test</title>
      </head>
      <body>
        {% for foo in lis %}
            <li>{{ foo }}</li>
        {% endfor %}
      </body>
</html>

别急,还没完呢,这不是我们主页面,我们的目的为了重复使用上面页面的代码(但必须上面界面是经过inclusion_tag传入的)。

index.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
      </head>
      <body>
        {% load mytag %}

        <b>第一次使用</b>
        {% my_inclusion_tag 2 %} <!-- 向那个页面传入值2,然后拿到它的页面 -->

        <b>第二次使用</b>
        {% my_inclusion_tag 5 %} <!-- 向那个页面传入值2,然后拿到它的页面 -->

      </body>
</html>

打开浏览器效果:

每次都可以传值给inclusion_tag,然后由inclusion_tag将值传递给某个页面,再然后那个页面产生的结果会返回到我们调用inclusion_tag的页面

总结:当某个区域需要反复使用inclusion_tag,那么得到数据不是固定的


模版导入

将写好的一个模板导入到另一个模板里面,类似于模块。

如:我们写的一个导航栏模板,写好之后其它任意模板都可以导入使用:

语法:{% include '模板文件' %}

headers.html

python 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>

</body>
</html>

yel.html 主页

python 复制代码
{% include 'headers.html' %} <!-- 放在任意位置都可以,笔者习惯性放在这里,更明确一些。 -->
<!DOCTYPE html>
<html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>index</title>
          <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
          <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
      </head>
      <body>
        Hello World!
      </body>
</html>

打开浏览器看看效果

模版继承

模板继承类似于模板导入,但不同的是继承分为:母版、子版。

  • 母版:正常页面布局,可以留出某块区域给子版进行使用
  • 子版:可以完全继承与模板,但是这就与导入无异了,所以子版可以在母版预留出来的区域继续编辑自己的内容
python 复制代码
		{% extends 'html文件名' %}			# 新建一个页面 第一行写入继承代码
	   	{% block 区域名称 %}					# 可以通过这个方式定位到页面的位置
	    	母版内容							# 这个地方填写新的代码
		{% endblock %}
		
	   	{% block 区域名称 %}			# 在模板划分的区域内编写内容
	    	子板内容
	    {% endblock %}

	 	母版在划定区域的时候一般都有三个区域:CSS区域、HTML文档区域、JS区域。
	 	目的就是为了让子版具有独立的CSS、JS以便于增加拓展性。
	 	
		在模板的head标签内:{% block css %}{% endblock %}
		在模板的body标签结尾:{% block javascript %}{% endblock %}
		
	    {% block css %}
		{% endblock %}
		
	    {% block content %}
		{% endblock %}
		
	    {% block js %}
		{% endblock %}
		
	   	'''子板中还可以使用母板的内容  {{ block.super }} 	让他使用之前原主页的内容'''	
相关推荐
聪明的墨菲特i2 分钟前
Django前后端分离基本流程
后端·python·django·web3
工业3D_大熊8 分钟前
【虚拟仿真】CEETRON SDK在船舶流体与结构仿真中的应用解读
java·python·科技·信息可视化·c#·制造·虚拟现实
SEEONTIME17 分钟前
python-24-一篇文章彻底掌握Python HTTP库Requests
开发语言·python·http·http库requests
Bearnaise17 分钟前
PointMamba: A Simple State Space Model for Point Cloud Analysis——点云论文阅读(10)
论文阅读·笔记·python·深度学习·机器学习·计算机视觉·3d
hlsd#1 小时前
go mod 依赖管理
开发语言·后端·golang
哇咔咔哇咔1 小时前
【科普】conda、virtualenv, venv分别是什么?它们之间有什么区别?
python·conda·virtualenv
infiniteWei1 小时前
【Lucene】什么是全文检索?解读结构化数据与非结构化数据
django·全文检索·lucene
陈大爷(有低保)1 小时前
三层架构和MVC以及它们的融合
后端·mvc
亦世凡华、1 小时前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
河西石头1 小时前
一步一步从asp.net core mvc中访问asp.net core WebApi
后端·asp.net·mvc·.net core访问api·httpclient的使用