Loading

Django模板层

一、模板介绍

Django的模板 = HTML代码 + 模板语法

存放在templates目录下的HTML文件就称为模板文件,如果我们想要返回 的HTML文件中的数据是动态的,那么就必须在HTML文件中嵌入变量,这就会用到Django的模板语法。

二、变量

在Django的模板语言中的变量语法:

View:{ ' HTML变量名 ' : ‘ views变量名 ’ }

HTML:{{ 变量名 }}

views.py 文件

from django.shortcuts import render
import time


def index(request):
    times = time.time()
    name = '小杨'
    name_list = ['小杨', '艾伦', '鲍勃']
    info_dict = {'name': '小杨', 'age': 18, 'job': '攻城狮'}

    class A:
        def __init__(self, hobby):
            self.hobby = hobby

        def func(self):
            return self.hobby

    # 也可以传入对象
    Bob = A('攻城狮')

    # 将数据传递给 index.html 文件进行渲染在发送给浏览器
    return render(request, 'index.html', {'times': times, 'Bob': Bob, 'name': name, 'name_list': name_list, 'info_dict': info_dict})

index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<!-- 接收数据进行渲染 -->
<p>{{ times }}</p>
<p>{{ name }}</p>
<p>{{ name_list.2 }}</p>    <!-- 取列表中索引为2的数据 -->
<p>{{ info_dict.age }}</p>  <!-- 取字典中键值为age的数据 -->
<p>{{ Bob.func }}</p>       <!-- 执行对象中的方法返回数据 -->

</body>
</html>

三、过滤器

过滤器类似于python的内置函数,用来把视图传入的变量加以修饰后在显示

过滤器的语法:{{ 变量名|过滤器 : 可选参数 }}

注意事项:

  1. 过滤器支持“ 链式 ” 操作 。
  2. 过滤器参数包含空格需要用引号包裹起来。
  3. '|' 左右没有空格

常用过滤器

default

如果一个变量是false或者是空,就使用给定的默认值。否则,使用变量的值。

{{ value|default:"默认值" }}

length

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

{{ value|length }}

filesizeformat

将值的格式转换为一个可读的,主要用于显示文件大小

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

{{ value|filesizeformat }}

slice

切片

{{ value|slice:"2:4" }}

date

格式化,若value = datetime.datetime.now()

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

safe

转义,若value是一串代码,就可以对其进行转义成非代码的,防止xss攻击。

{{ value|safe }}

truncatechars

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

{{ value|truncatechars:'6' }}	# 后面的三个省略号也算在6个字符里面

truncatewords

在一定数量的字后截断字符串,是截多少个单词。

{{ value|truncatewords:2 }}

cut

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

{{ value|cut:'移除的字符' }}

join

使用字符串连接列表。

{{ list|join:', ' }}

四、标签Tags

标签是为了在模板中完成一些特殊功能,语法为{% 标签名 %},一些标签还需要搭配结束标签 {% endtag %}

for 标签

1、遍历每一个元素

{% for food in foods_list %}
	<p>{{ food }}</p>
{% endfor %}

2、可以利用{% for obj in list reversed %}反向循环。

{% for food in foods_list reversed %}
	<p>{{ food }}</p>
{% endfor %}

3、遍历一个字典

{% for k, v in f_dict.items %}
   <p>{{ k }}:{{ v }}</p>
{% endfor %}

for ... empty

可选的{ % empty % } 从句,给出的组是空的或者没有被找到时,执行的操作

{% for food in foods_list %}
    <p>{{ food }}</p>

{% empty %}
    <p>没有foods_list,或者foods_list为空</p>
{% endfor %}

for循环的其他方法

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

if 标签

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

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

{% if num > 100 or num < 0 %}
    <p>条件1满足</p>  		<!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
    <p>条件1不满足,条件2满足</p>
{% else %}  		  <!--也是在if标签结构里面的-->
    <p>条件都不成立,执行我吧</p>
{% endif %}

with 标签

给一个复杂的变量起别名

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

或者

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

csrf_token 标签

用于跨站请求伪造保护

在form表单里面任何位置写上。

工作原理:

1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如下:

<input type="hidden" name="csrfmiddlewaretoken" value="dmFo...O5">

2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份

实例:

<form action="" method="post">
    {% csrf_token %}
    用户名:<input type="text">
    密码:<input type="password">
    <input type="submit">
</form>

五、自定义过滤器和标签

当内置的过滤器和标签无法支持我们的需求时,就使用自定义标签或过滤器

自定义过滤器

步骤:

1、在文件夹app01中创建子文件夹 templatetags (文件夹只能是templatetags)

2、在 templatetags 新建任意 .py 文件,如 mytags.py,在该文件中自定义过滤器或标签。

内容如下

# mytags.py 文件
from django import template  # 导入的模块

register = template.Library()  # register 固定的名字 注册器


# 自定义过滤器

@register.filter
def my_filter1(v1):         # 不带参数的
    # 对 v1 的操作
    v = v1 + '操作'
    return v
"""
使用:HTML文件中 
{% load 文件名 %}      --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{{ value1|my_filter1 }}    --> 无参数
把 value1 的值传入给 v1 ,做处理后返回。
"""


@register.filter
def my_filter2(v1, v2):     # 带参数的过滤器(最多只能带两个)
    # 对 v1 v2 的操作
    v = v1 + v2
    return v
"""
使用:HTML文件中 
{% load 文件名 %}      --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{{ value1|my_filter1:value2 }}    --> 有参数
把 value1 的值传给 v1 ,参数 value2 传给 v2 ,做处理后返回
"""

自定义标签

步骤和自定义过滤器一样:

# mytags.py 文件
from django import template  # 导入的模块

register = template.Library()  # register 固定的名字 注册器


@register.simple_tag
def my_tag(v1, v2, v3):     # 自定义的标签可以定义多个参数
    # 对传入的参数处理
    v = v1 + v2 + v3
    return v
"""使用:HTML文件中
{% load 文件名 %}      --> 在HTML文档中必须先加载存有自定义过滤器和标签的文件
{% my_tag value1 value2 value3 %}    
把 value1=v1 value2=v2 value3=v3 传入标签中,处理后返回。
"""

六、模板继承

在Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的 “骨架” 模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

模板主要围绕三种标签的使用:include标签、extends标签、block标签。

模板继承之include标签

include标签也称为组件

组件和插件的简单区别:

  1. 组件是提供某一完整功能的模块。
  2. 而插件更倾向于封闭某一功能方法的函数。

作用:在一个HTML模板文件中,引入或者重复使用另一个模板文件的内容。

{% include '模板名称' %}

实例:

把整个 test.html 模板引入到 index.html 模板中

<!-- test.html 文件 -->
<div>
    <ul>
        <li>小杨</li>
        <li>小明</li>
        <li>鲍勃</li>
        <li>艾伦</li>
    </ul>
</div>


<!------------------------------------------------------------------------>
<!-- index.html 文件 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>
{% include 'test.html' %} <!-- 此处,当此文件发送给客户端的时候,就变成了test.html文件的内容了 -->
</div>

</body>
</html>

模板继承之extends标签、block标签

作用:在一个HTML模板文件中,引入或者重复使用另一个模板文件的内容。

include 有的功能 extends 全都有,但是 extends 可以搭配一个block标签,用于在继承的基础上增加新的内容

模板制定钩子

{% block 钩子名 %}
<!-- 另一HTML模板引入此模板时可以从此处填充自己的内容 -->
{% endblock 钩子名 %}	

新模板引入旧模板,并从旧模板钩子处填充新内容

{% extends '模板名' %}

<!-- 用新内容完全覆盖了父模板钩子中的内容 -->
{% block 钩子名 %}
	<p> Hello World... </p>
{% endblock 钩子名 %}

实例:

1、制定一个模板 base.html ,它定义了一个页面上面的导航栏,和页面左边的菜单栏,网页中间由我们引入模板时自行填充自己的内容。

|---------------------|
|		导航栏		    |
|-------|-------------|
|   菜  |			 |	
|	单  | 自行填充的内容 |
|	栏  |			 |
|-------|-------------|

模板 base.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .top {
            height: 100px;
            background-color: red;
        }
        .left {
            height: 400px;
            width: 20%;
            background-color: aqua;
            float: left;
        }
        .centre {
            float: right;
            height: 400px;
            width: 80%;
            background-color: green;
        }
    </style>

</head>
<body>

<div class="top">
    <a href="">导航一</a>
    <a href="">导航二</a>
    <a href="">导航三</a>
    <a href="">导航四</a>
</div>

<div class="counter">
    <div class="left">
        <p><a href="">菜单一</a></p>
        <p><a href="">菜单二</a></p>
        <p><a href="">菜单三</a></p>
        <p><a href="">菜单四</a></p>
    </div>

    <div class="centre">
    {% block centent %}
        <ul>
            <li>信息1</li>
            <li>信息2</li>
            <li>信息3</li>
        </ul>
        <!-- 另一HTML模板引入此模板时可以从此处填充自己的内容 -->

    {% endblock centent %}
    </div>
</div>

</body>
</html>

2、index.html 模板引入base.html 模板,并在 base.html 模板钩子处添加新内容。

{% extends 'base.html' %}

{% block centent %}
{{ block.super }}	————> 该变量会将父模板中 centent 中原来的内容继承过来


<!--在继承父模板内容的基础上新增的标签-->
<form action="" method="post">
    {% csrf_token %}
    用户名:<input type="text">
    密码:<input type="password">
    <input type="submit">
</form>

{% endblock centent %}

3、当启动 Django 访问 index.html 页面时返回的内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .top {
            height: 100px;
            background-color: red;
        }
        .left {
            height: 400px;
            width: 20%;
            background-color: aqua;
            float: left;
        }
        .centre {
            float: right;
            height: 400px;
            width: 80%;
            background-color: green;
        }
    </style>

</head>
<body>

<div class="top">
    <a href="">导航一</a>
    <a href="">导航二</a>
    <a href="">导航三</a>
    <a href="">导航四</a>
</div>

<div class="counter">
    <div class="left">
        <p><a href="">菜单一</a></p>
        <p><a href="">菜单二</a></p>
        <p><a href="">菜单三</a></p>
        <p><a href="">菜单四</a></p>
    </div>

    <div class="centre">
    	<!-- 此处被替换 -->
        <form action="" method="post">
            <input type="hidden" name="csrfmiddlewaretoken" value="WE..DF">
            用户名:<input type="text">
            密码:<input type="password">
            <input type="submit">
        </form>
        
    </div>
</div>

</body>
</html>

总结:

  1. 标签extends必须放在首行,base.html 中 block 越多控制性越强
  2. include 仅仅只是完全引用了其他模板文件,而 extends 却可以搭配 block 在引用的基础上进行扩写
  3. 变量 {{ block.super }} 可以重用父类的内容,然后再父类基础上增加新内容,而不是完全覆盖
  4. 在一个模板中不能出现重名的block标签。

七、静态文件配置

在网站中我们需要用到大量的css、js、图片等,这些都叫做静态文件。

关于Django中静态文件的配置,我们就需要在 settings 配置文件里面写上这样的内容:

1、例如在项目中创建一个 static_file 文件夹来存放静态文件。

注意:别名可以随便写名字,但是如果改了名字,别忘了如果前端页面如果是通过 /别名/静态文件 调用静态文件的话,前端页面的静态文件也要更改成一样的

STATIC_URL = '/static/'		# 别名
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static_file')	
]

2、前端页面引入静态文件

方式一:不推荐,别名如果有变化,所有应用别名的地方都需要改

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/css/my.css">
</head>
<body>

<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="/static/img/my.png" alt="">

<script src="/static/js/my.js"></script>

</body>
</html>

方式二:推荐,通过 load static 来找到别名,通过别名映射路径的方式来获取静态文件

标签static会接收传入的参数,然后这根据settings.py中变量STATIC_URL的值拼接出一个完整的路径

{% load static %}   <!-- 注意:必须先加载文件static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 注意:此处的static是一个定义在 static.py 中的一个标签,名字与文件名一样 -->
    <link rel="stylesheet" href="{% static 'css/my.css' %}">
</head>
<body>

<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="{% static 'img/my.png' %}" alt="">

<script src="{% static 'js/my.js' %}"></script>

</body>
</html>

方式三:get_static_prefix 标签

和上面的效果一样,不过只是用法不同。get_static_prefix 不能传参,只能拼接,如下:

{% load static %}	<!-- 注意:必须先加载文件static.py -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% get_static_prefix %}css/my.css">
</head>
<body>

<h1 class="c1" id="d1">点我就弹窗</h1>
<img src="{% get_static_prefix %}img/my.png" alt="">

<script src="{% get_static_prefix %}js/my.js"></script>

</body>
</html>
posted @ 2021-06-09 20:15  Mr-Yang`  阅读(280)  评论(0编辑  收藏  举报