09. django模版层

一、模版简介

1、为什么不直接将HTML编码到视图层?

- 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 
- 站点设计的修改往往比底层 Python 代码的修改要频繁得多,
- 因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。

- Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。
-  设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。

- 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,
- 远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

基于上面所述的原因,我们将页面的设计和python代码分离开,会使得项目更干净、更容易维护。

我们使用django的模版系统 (Template System)来实现这种模式

2、python的模版使用方式:

  • HTML代码+模版语法
def current_time(req):
    # ================================原始的视图函数
    # import datetime
    # now=datetime.datetime.now()
    # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now


    # ================================django模板修改的视图函数
    # 方式一
    # from django.template import Template,Context
    # now=datetime.datetime.now()
    # t=Template('<html><body>现在时刻是:<h1>{{current_date}}</h1></body></html>')
    # #t=get_template('current_datetime.html')
    # c=Context({'current_date':str(now)})
    # html=t.render(c)   # html是渲染后的字符串
    #
    # return HttpResponse(html)


    #方式二:(推荐使用)
    import datetime
    now=datetime.datetime.now()
    return render(request, 'current_datetime.html', {'current_date':str(now)})

3、模版语法重点:

变量相关:{{ 变量名 }}
	1、深度查询,用句点符
    2、过滤器
逻辑相关(标签):{{% %}}

4、注释

# 1、模版语法的注释:
{#  模板语法的注释   #}

# 2、前端注释:
<!--
前端html的注释
-->

二、模版语法之变量

DTL:Django Template Language

1、模版中使用{{python变量}}

视图层view.py :

from django.shortcuts import render, HttpResponse
from django.utils.safestring import mark_safe

def index(request):
    num = 10
    ss = 'hello world'
    b = False
    ll = [1, 2, 3,4]
    dic = {'name': 'cc', 'age': 18}

    def test():
        print('我是test')
        return 'test函数'

    class People():
        def __init__(self, name):
            self.name = name

        def print_name(self):
            return self.name
        def __str__(self):
            return self.name

    p=People('cc')

    # return render(request, 'index.html',{'num':num,'ss':ss,'b':b})  # 一个一个往字典中写key:value
    #locals() 把当前作用域下所有的变量,都传到context字典中
    return render(request, 'index.html',locals())

index.html中:

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

<h1>模版语法之变量</h1>

<p>数字:{{ num }}</p>
<p>字符串:{{ ss }}</p>
<p>布尔:{{ b }}</p>
<p>列表:{{ ll }}</p>
<p>字典:{{ dic }}</p>
<p>函数:{{ test }}</p>
<p>对象:{{ p }}</p>

</body>
</html>

三、模版语法之深度查询句点符

view.py

from django.shortcuts import render, HttpResponse
from django.utils.safestring import mark_safe

def index(request):
    num = 10
    ss = 'hello world'
    b = False
    ll = [1, 2, 3, {'name':"cc"}]
    dic = {'name': 'cc', 'age': 18}

    def test():
        print('我是test')
        return 'test函数'

    class People():
        def __init__(self, name):
            self.name = name

        def print_name(self):
            return self.name
        def __str__(self):
            return self.name

    p1=People('cc')
	link1 = '<a href-"https://www.baidu.com">点我<a>'
    
    link2 = mark_safe(link1) 
    
	input_1 = '<p>用户名:<input type="text" name="name"></p>'
    
    input_2 = mark_safe(input_1)
    
    script_1='''
    <script>
    alert('你被攻击了')
    </script>
    '''
    
    script_2 = mark_safe(script_1)
    return render(request, 'index.html',locals())

index.html

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

<h1>模板语法之句点符的深度查询</h1>
<p>列表的第一个元素:{{ ll.1 }}</p>
<p>字典的name对应的值:{{ dic.name }}</p>
<p>列表的第三个元素的name对应的值:{{ ll.3.name }}</p>
<p>函数执行,直接写函数名即可:{{ test }}</p>
<p>函数如果有参数?不支持</p>
<p>对象调用方法: {{ p1.print_name }}</p>
<p>对象调用属性: {{ p1.name }}</p>
<hr>
<a href="https://www.baidu.com">点我</a>
<p>a标签的字符串: {{ link1 }}</p>
<p>a标签的字符串,显示成a标签: {{ link2 }}</p>

<p>用户名:<input type="text" name="name"></p>
<p>input标签:{{ input_1 }}</p>
<p>input标签,显示成标签:{{ input_2 }}</p>

<p>js原封不动显示:{{ script_1 }}</p>

{{ script_2 }}
</body>
</html>

四、模版渲染成标签还是原封不动的字符串

  • xss攻击是什么?
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,
使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,
但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。
攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容
  • django是如何处理xss攻击的,原理是什么?

    # 1、后台视图或者模板中导入escape方法
    from django.utils.html import escape
    
    # 2、前端html页面中,对可能会出现攻击的字段增加escape过滤
    示例:
    {{ user.username|escape }}
    

五、过滤器

语法:

# 1、
{{ 参数1|过滤器名称[:参数2] }}
# 过滤器最多传两个值,最少一个,(参数1可以是变量名或者变量值,参数2必须是字符串形式的)
# 示例:
{{ "hello world"|slice:'2:3'}}

# 2、链式调用:上一个过滤器的结果继续被下一个过滤器处理
{{ 变量名|过滤器1|过滤器2 }}

1、常用内置过滤器

  • default
{{ num|default:'nothing' }}
# num如果是False或者空或者None,使用default后设置成指定值
  • default_if_none
{{ value|default_if_none:"None..." }}
# 作用:如果只针对value是None这一种情况来设置默认值,需要使用
# 只有在value=None的情况下,才会输出“None...”
  • length
{{ dic|length }}
# 返回变量的长度,参数1可以直接写值如:{"k1":111, "k2":222}
# 对字符串、列表、字典等容器类型都起作用
  • filesizeformat
{{ num|filesizeformat }}
# 将一个值格式化为一个可读的文件尺寸(如:16KB、3.5GB等)
  • date
{{ value|date:"Y-m-d H:i:s"}}
# 作用:将日期按照指定的格式输出 value可以是 datetime.datetime.now()
  • slice
{{ value|slice:"0:2"}}
# 作用:对输出的字符串进行切片操作,顾头不顾尾
  • truncatechars
{{ value|truncatechars:8 }}
# 作用:如果字符串多于指定的字符数量,那么将会被截断,截断的字符串将以...结尾,
# 注意:8个字符串中也包括"..."
  • truncatewords
{{ value|truncatewords:2}}
# 作用与truncatechars差不多,但是truncatewords是按照单词截断的、
# 并且末尾的...不能算作单词
  • safe
{{ link1|safe }}
# 作用:经过过滤器safe的处理,浏览器在进行解析时就会把link1当做超链接,不加safe过滤器就会当做普通字符显示

六、模版语法之标签

标签看起来像是这样的: {% tag %}。
标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %}

1、常用标签

  • for标签
# for的用法
# 示例一:
{% for l in ll %}	
    <p>
    	<a href="http://127.0.0.1:8080/{{ l }}">{{ l }}</a>
    </p>
{% endfor %}

# 示例二:
{% for k,v in dic.items %}
    <p>key值:{{ k }},  value值:{{ v }}</p>
{% endfor %}

# 示例三:
<table border="1">
    <tr>
        <td>id</td>
        <td>用户名</td>
        <td>年龄</td>
    </tr>
    {% for dic in user_list %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ dic.name }}</td>
            <td>{{ dic.age }}</td>
        </tr>
    {% endfor %}
</table>

# 在for标签内部一直有一个forloop对象,是一个字典
 {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}
	- forloop.counter0:0开始,每循环一次加1
	- forloop.counter:从1开始,每循环一次加1
	- forloop.revcounter:从列表长度开始,每循环一次减一
	- forloop.first:判断是不是循环的第一个
	- forloop.last:判断是不是循环的最后一个
	- forloop.parentloop:父级forloop对象,本层循环的外层循环(for循环嵌套)
  • for…empty
<ul>
    {% for l in ll %}
        <li>{{ l }}</li>
    {% empty %}
        <li>nothing</li>
    {% endfor %}
</ul>

# 当列表ll中为空时,将在浏览器中显示指定的“nothing”
  • if标签
{% if b %}
    <p>b是True</p>
{% else %}
    <p>b是False</p>
{% endif %}

# 条件判断,if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断
# 也支持if...elif...else...endif
  • with
{% with forloop.parentloop.counter as aaa %}
    {{ aaa }}
{% endwith %}

# 作用:给xxx变量起别名,则下面可以使用别名访问值
  • csrf_token
{% csrf_token %}

# 作用:这个标签用于跨站请求伪造保护
# 用法:在html页面的form表单中写上{% csrf_token %}

2、注意事项

# 1、django的模板语言不支持连续判断,即不支持{% if a>b>c %}...{% endif %}

# 2、django的模板语言中属性的优先级大于方法
def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})
如上,我们在使用render方法渲染一个页面的时候,传的字典d有一个key是items并且还有默认的d.items()方法,此时在模板语言中写:
{{ data.items }}
默认会取字典d的items的value值100

七、自定义标签与过滤器

1、自定义过滤器

# 步骤:
    (1) 在settings中的INSTALLED_APPS里配置当前app,否则django无法找到自定义的simple_tag
    
    (2) 在app中创建templatetags模块(模块名不能改,只能叫templatetags)
    
    (3) 在模块内新建.py文件(如:my_tags.py)
    
    (4) 写代码(过滤器)
    	from django import template
        
        register = template.Library()
        
        @register.filter
        def my_upper(value):
            return value.upper()
    (5) 模板中使用:先load,再使用
    	{% load my_tags %}
        {{ 'aa'|my_upper }}

2、自定义标签

(1) 在settings中的INSTALLED_APPS里配置当前app
    
(2) 在app中创建templatetags模块
    
(3) 在模块内新建.py文件(如:my_tags.py)

(4) 写代码(标签)
	from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()
    @register.simple_tag
    def my_csrf():
        import uuid
        res = uuid.uuid(4)
        return mark_safe('<input type="hidden" name="csrfmiddlewaretoken" value="%s">'%res)
 
(5) 模板中使用:先load,再使用
	{% load my_tags %}
    {% my_csrf %}
    {% my_tag 111 222 333 %}    # 如果my_tag函数需要多个参数,那么直接加载后面

八、模板的导入与继承

1、模板的导入

(1)第一步:新建一个xxx.html,把模板写入:
    <div class="panel panel-danger">
    	<div class="panel-heading">
        	<h3 class="panel-title">重金求子</h3>
        </div>
        <div class="panel-body">
        	详情点击:<a href="http://www.baidu.com">疯狂点我</a>
        </div>
    </div>

(2)第二步:在需要使用的地方导入
	{% include "xxx.html" %}

2、模板的继承(母版)

(1) 第一步:写一个母版,在母版里面写空盒子
	{% block top %}
    
    {% endblock %}
   
(2) 第二步:某个页面如果要使用母版,就先引入,再扩写盒子
	{% extends "base.html" %}
    {% block top %}
    	index页面
    {% endblock %}

九、静态文件相关

有三种设置方式:

# 第一种:
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
   
# 第二种:
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">

# 第三种:
{% load static %}
<link rel="stylesheet" href="{% get_static_prefix %}bootstrap/css/bootstrap.min.css">

# 特殊用法:
{% load static %}
{% static "image/hi.jpg" as mypicture %}
<img src="{{ myphoto }}"></img>

{% load static %}
{% get_static_prefix as static %}
<img src="{{ static }}image/hi.jpg" alt="Hi!">

十、inclusion_tag的使用

# 可以生成一片模板中的代码块
# 使用步骤:
(1) 在settings中的INSTALLED_APPS里配置当前app
    
(2) 在app中创建templatetags模块
    
(3) 在模块内新建.py文件(如:my_tags.py)

(4) 写代码(inclusion_tag)
	from django import template
    
    register = template.Library()
    
    @register.inclusion_tag('left.html')
    def left(num):
        dic = {i:'第%s页' % i for i in range(num)}     
        # 返回值必须是一个字典形式
        return {'data': dic}
 	
    @register.inclusion_tag('popular.html')
    def popular(title, url):
        return {'title':title, 'url':url}
    
(5) 模板中使用:先load,再使用
	{% load my_tags %}  //先导入
    {% left 5 %}		//5就是参数
    {% popular 'xxx名字' 'url地址' %}
  • 与tag的区别:
- tag:需要在视图层代码中写html内容
- inclusion_tag:视图层代码与模板分离
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值