Django:模版系统

一 语法

变量相关的用 {{ }}

逻辑相关的用{% %}

二 变量

在Django的模版系统中,变量使用方法:{{ 变量名 }}

当模版引擎遇到一个变量,他将计算这个变量,然后用结果替换掉它本身。变量的命名规则与python变量的命名规则一样。

深度查询据点符 "." 在模版中有特殊的含义,当模版遇到 "." ,它将以这样的顺序查询:

字典查询

属性或者方法查询

数字索引查询

注意事项:

1.如果计算结果的值是可以调用的,它将被无参数的调用。调用的结果将成为模版的值

2.如果使用的变量不存在,模版系统将插入string_if_invalid选项的值,它被默认设置为 ""(空字符串)

例子:

views中的代码

def index(request):
    nlst = ['jackma','tonyma','robinli','jackychen']
    userinfo = {'name':'jackma','age':33,'money':'more'}
    class Person:
        def __init__(self):
            self.kind = 'yellow race'
        def dream(self):
            return 'to be stronger'
    po = Person()
    return render(request,'app03_index.html',{'namelist':nlst,'userinfo':userinfo,'person':po})

模版中支持的写法

#可以嵌套在各种标签中
<ul>
    <li>{{ namelist }}</li>
    <li>{{ userinfo.money }}</li>
    <li>{{ person.kind }}</li>
    <li>{{ person.dream }}</li>
</ul>

三 过滤器

在Django的模版中,通过使用过滤器来改变变量的显示

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

使用管道符 "|" 来应用过滤器。

例如:{{ name|lower }}会讲name变量应用lower过滤器之后再显示它的值。lower在这里是将文本小写

注意事项:

  1. 过滤器支持链式操作,即一个过滤器的输入作为另一个过滤器的输入

  2. 过滤器可以接受参数,例如:{{ sss|truncatewords:30}},这将显示sss的前30个单词

  3. 过滤器参数包含空格的话,必须使用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素{{ list|join:', '}}

  4. '|'左右没有空格

内置过滤器

# 1.default :如果一个变量是false或者为空,使用给定的默认值。否则使用变量的值
{{ value|default:'nothing' }}  #如果value没有传值或值为空的话就显示nothing

# 2.length    :返回值的长度,作用于字符串和列表
{{ value|length }} 
value=['a','b','c','d']
{{ value|length }} # 显示 4 

# 3.filesizeformat:将数值格式化为以kb/MB/bytes为单位的值
{{ vlue|filesizeformat }}

# 4.slice:切片,
{{ value|slice:'2:-1'}}

# 5.date:格式化,如果value = datetime.time.now()
{{ value|date:'Y-m-d H:i:s'}}

# 6.safe:Django模版中在进行模版渲染的时候会对HTML标签和JS等语法标签进行自动转义,这是为了安全,Django担心这是用户提交的数据,比如如果有人在评论框输入一段js代码,那么提交这条内容为js代码的评论,js代码就会执行,这就是xss攻击。这样就会存在严重的安全隐患,所以浏览器为了不让你这么搞,给你转义了。但是有时候我们不希望被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果一个单独的变量我们可以通过过滤器 "|safe"的方式告诉Django,这段代码是安全的不需要转义
value = "<a href='#'>click me</a>"
{{ value|safe }}

# 7.truncatechars:按字符截断字符串,以"..."为结尾
value = 'abcdefghijk'
{{ value|truncatechars:7}}# 返回abcd... ,三个省略号也属于截断的7个字符

# 8.truncatewords:按单词截断
value = 'there is a book of computer '
{{ value|truncatewords:3}} # 返回 there...  

# 9.cut:移除value中所有的与给出的变量相同的字符串
value = 'this is a book'
{{ value|cut:' '}} # 返回 thisisabook

# 10.join:类似python中的str.join(list)
{{ list|join:'+'}}

四 标签Tags

标签:{% tag %}。一些在输出中创建文本,一些通过循环或者逻辑来控制流程

有些标签需要开始和结束标签{% tag %}...tag content...{% endtag%}

for 标签

遍历每一个元素:写个for,然后tab键自动生成for循环结构

{% for person in person_list %}
    <p>{{ person.name }}</p>  <!--凡是变量都要用两个大括号括起来-->
{% endfor %}

可以利用{% for obj in list reversed %}反向完成循环。
    
遍历字典
{% for k,v in userinfo %}
    <p>{{ k }}:{{ v }}</p>
{% endfor %}

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


{% for k,v in userinfo %}
    <p>{{ forloop.counter0 }} {{ k }}:{{ v }}</p>
{% endfor %}

for ...empty

#for标签有一个可选的{% empty %}从句,以便在给出的组是空的或者没有 没有被找到时,可以有所操作

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

if标签

#{% if %}会对一个变量求职,如果它的值是“True”,对应的 内容块会输出
#if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。

{% if num > 100 or num < 0 %}
    <p>无效</p>  <!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}  <!--也是在if标签结构里面的-->
    <p>凑活吧</p>
{% endif %}

#也可以只有if 和 else
{% if user_list|length > 5 %}  <!--结合过滤器来使用-->
  七座豪华SUV
{% else %}
    黄包车
{% endif %}

with标签

#使用一个简单的名字缓存一个复杂的变量,多用于给一个复杂的变量起别名

{% with total=business.employees.count %}    # 等号左右不要加空格
    {{ total }} <!--只能在with语句体内用-->
{% endwith %}

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

csrf_token

这个标签用户跨站请求伪造保护
在html页面的form表单里面,任何位置写上 {% csrf_token %},这个东西在模版渲染的时候替换成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隐藏的,这个标签的值是个随机字符串,提交数据到服务器的时候,这个东西也被提交了。首先这个东西使我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你携带这个内容,服务器就能识别,如果没有携带这个,服务器就禁止你访问,在服务器端也存有这个值

五 模版继承

模版继承可以让你创建一个基本的页面框架,它包含站点的全部元素,并且可以定义能够被自模版覆盖的blocks

{% extends "base.html" %}

1 创建模板,添加钩子,可以添加很多
    {% block 钩名 %}
        模板
    {% endblock 钩名 %}

2 其他html文件中要使用它
    开头 {% extends 'Muban.html' %}
    {% block 钩名 %}
        {{ block.super }}
        不同的部分
    {% endblock 钩名 %}

六 组件

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

{% include 'navbar.html' %}

七 自定义标签和过滤器

1.在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag

2.在app中创建templatetags模块(文件夹),名字只能是templatetags

3.创建任意 .py文件,如:mytags.py

#在app中创建的templatetags文件夹中创建 sim_tag.py文件
from django import template

register = template.Library()   # register的名字是固定的 ,不可改变

@register.filter    # 自定义过滤器
def filter_multi(v1):    
    return v1**2

@register.filter
def filter_sum(v1,v2):
    return v1+v2

@register.simple_tag    # 自定义标签
def sim_tag_multi(v1,v2,v3):
    return v1+v2+v3


# 在使用自定义标签的html文件中导入创建的sim_tag.py
{% load sim_tag %}

# 在html文件中使用 simple_tag 和 filter
{% load sim_tag %}

<p>{{ a|filter_multi }}</p>    # 给filter传递一个参数,就是从views中接收到的
<p>{{ a|filter_sum:21 }}</p>    # 给filter传递两个参数,最多两个参数

<p>{% sim_tag_multi a 11 22 %}</p>    # 自定义标签的使用,可以传递多个参数

inclusion_tag:多用于返回html代码片段

1. app应用文件夹中创建一个templatetags文件件,必须是这个名字
2. templatetags文件夹中创建一个 xx.py文件,文件名字随便起
3. 创建自定义inclusion_tag

    from django import template
    register = template.Library()
    
    @register.inclusion_tag('inclusiontag.html')
    def func(v1):
        return {'info':v1}
    
4. func的return数据,传给了inclusiontag.html,作为模板渲染的数据,将inclusiontag.html渲染好之后,作为一个组件,生成到调用这个func的地方

5.在inclutiontag.html中使用 inclution_tag传递参数
    <ul>
        {% for d in info %}
            <li>{{ d }}</li>
        {% endfor %}
    </ul>

6. 在app03_index.html中使用inclution_tag
    {% load sim_tag %}    # 导入创建的sim_tag.py
    {% func lst %}    # 这里调用func函数,lst接受的是从views中传递过来的值

八 静态文件相关

#Django引用静态文件的步骤
1.项目目录下创建一个用来存放静态文件的文件夹,一般命名为statics
2.在项目settings.py文件中写上
    STATIC_URL = '/static/'    # 静态文件夹的别名,在html文件中用这个目录引用静态文件

    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'statics')    # 创建的静态文件夹名
    ]
3.在引用静态文件的html文件中,直接引用
    <link rel="stylesheet" href="/static/test.css">   # 使用别名引用自定义的css文件
    
4.另外一种引用静态文件的方式
    在html文件的第一行写:{% load static %}
    引入静态文件:
        <link rel="stylesheet" href="{% static 'test.css' %}">
5.使用get_static_prefix 引用静态文件
    在html文件的第一行写:{% load static %}
    引入静态文件:
    <link rel="stylesheet" href="{% get_static_prefix %}test.css">

js、css、img等都叫做静态文件,那么关于django中静态文件的配置,我们就需要在settings配置文件里面写上这写内容:

# STATIC_URL = '/xxx/' #别名,随便写名字,但是如果你改名字,别忘了前面页面里面如果你是通过/xxx/bootstrap.css的时候,如果这里的别名你改成了/static/的话,你前端页面的路径要改成/static/bootstrap.css。所以我们都是用下面的load static的方式来使用静态文件路径
STATIC_URL = '/static/' #别名

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'jingtaiwenjian'), #注意别忘了写逗号,第二个参数就是项目中你存放静态文件的文件夹名称
]

 目录:别名也是一种安全机制,浏览器上通过调试台你能够看到的是别名的名字,这样别人就不能知道你静态文件夹的名字了,不然别人就能通过这个文件夹路径进行攻击。

 前端页面引入静态文件的写法,因为别名也可能会修改,所以使用路径的时候通过load static来找到别名,通过别名映射路径的方式来获取静态文件

{% static %}

{% 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>

注意一个html文件中写相对路径时需要注意的一个问题:

<form action="/login/"></form>
<img src="/static/1.jpg" alt="">
等标签需要写路径的地方,如果写的是相对路径,那么前置的/这个斜杠必须写上,不然这个请求会拼接当前网页的路径来发送请求,就不能匹配我们的后端路径了

 

posted @ 2020-08-04 12:35  muchen  阅读(151)  评论(0编辑  收藏  举报