Django-模板层

一、django模板使用的两种方式

本质:打开模板文件,字符串替换,retern HttpRespnse('替换完的字符串')

view.py

# 方式一
def index(request):
    return render(request,'time.html',context={'current_date':str(now),'title':'这是自定义标题'})

def index(request):
    current_date = str(now)
    title = '这是自定义标题'
    return render(request,'time.html',context={'current_date':current_date,'title':title})

# 方式二(也叫页面静态化,提高网站并发量,以下只是页面静态化最基本的使用方式,实际中还需要其他技术引入)
    now=datetime.datetime.now()
    from djangotest import settings
    import os
    path=os.path.join(settings.BASE_DIR,'templates','time.html')
    ss=open(path,'r',encoding='utf-8').read()
    t=Template(ss)
    c=Context({'current_date':str(now),'title':'这是自定义标题'})
    html=t.render(c)  # html是渲染后的字符串
    return HttpResponse(html)

time.html

使用{{}}包括的变量,就会把这些变量渲染出来替换掉,详细看下一部分

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
    现在时刻是:<h1>{{current_date}}</h1>
</body>
</html>

二、模板语法之变量

DTL:Django Template Language,每个编程语言都会有自己的模板语法,比如java里的jsp

views.py

# 模板中使用 {{python变量}}
def index(request):
    num = 10
    ss = 'yang is handsome'
    b = False
    ll = [1, 2, 43]
    dic = {'name': 'yang', 'age': 18}

    def test():
        print('我是test')
        return '这是测试函数test的返回值'

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

        def print_name(self):
            return self.name
        # 如果不重写__str__ DTL会把对象的内存地址打印出来
        def __str__(self):
            return self.name

    p=Person('yang')

    return render(request, 'index.html',{'num':num,'ss':ss,'b':b})
    #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的显示方式,可以重写__str__方法-->
<p>对象:{{ p }}</p>

</body>
</html>

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

我们可以使用.(点)把一些属性或者数据点出来。

在DTL中不支持括号,所以如果要执行函数,直接写函数名即可,因为DTL不支持括号,所以不支持用函数传递参数,即我们只能写不带参数的函数传到前端。虽然不支持函数传递参数,但是我们可以通过过滤器或者标签传递参数到视图函数中,然后进行处理。

1.句点符举例

views.py

def index(request):
    ll = [1, 2, 43, {'name': 'yang'}]
    dic = {'name': 'yang', 'age': 18}

    def test():
        print('我是test')
        return '这是测试函数test的返回值'

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

        def print_name(self):
            return self.name

        def __str__(self):
            return self.name

    p = Person('yang')

    link1 = '<a href="https://www.baidu.com">点我<a>'

    link2 = mark_safe(link1)  # from django.utils.safestring import mark_safe,需要先导入

    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

<h2>模板语法之句点符的深度查询</h2>
<p>列表的第一个元素:{{ ll.1 }}</p>
<p>字典的name对应的值:{{ dic.name }}</p>
<p>列表的第三个元素的name对应的值:{{ ll.3.name }}</p>
<p>函数执行,直接写函数名即可:{{ test }}</p>
<p>函数如果有参数?不支持</p>
<p>对象调用方法: {{ p.print_name }}</p>
<p>对象调用属性: {{ p.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 }}

2.xss攻击

xss攻击是利用网页的漏洞,将一些攻击性代码放入网页中,当用户执行网页的时候,攻击性代码也随之运行,从而达到攻击效果。通常情况,这些恶意程序是js,java,VBScript但不局限于此。

django已经帮我们处理了xss攻击,django利用escape转义来处理,即

<div>就是html的关键字,如果要在html页面上呈现<div>,其源代码就必须是&lt;div&gt;转义其实就是把HTML代码给转换成HTML实体,让他原原本本的显示出来不带代码这样的特殊含义
如果对于一些代码我们想让他具有代码的功能,那么我们可以使用mark_safe函数或者safe过滤器

四、过滤器

有许多的过滤器,如default,length,filesizeformat,date,slice,truncatechars,safe等等

较为重要的是date和safe

{{参数1|过滤器名字:参数2}}
过滤器最多传两个值,最少一个值  {{'HelloWord'|slice:'2:3'}}
# 记住
# 过滤器之date:显示时间,控制输入来的时间格式,比如只显示年或者只显示年月日等,且大小写还有不同
ctime = datetime.datetime.now()
{{ ctime|date:'Y年m月d日-------H时i分s秒' }}
{{ ctime|date:"Y-m-d" }}
{{ ctime|date:"Y-M-D" }}
-----------------------------------
2020年10月13日-15时16分22秒
2020-10-13
2020-Oct-Tue

# 过滤器之safe:将想显示的代码过滤出来,不打印其实体
link1 = '<a href="http://www.baidu.com">点击跳转百度</a>'
{{ link1|safe }}

# 了解
# filesizeformat过滤器,将值格式化为一个 “人类可读的” 文件尺寸(例如13kb,52MB)
num = 1341414124
{{ num|filesizeformat }}  
------------------
1.2GB

# slice过滤器,切割
ss = '12345678987654321'
{{ ss|:slice"7:11" }}
------------------------------
8987

# truncatechars过滤器:只显示输入参数的字符数,且因为...占了三个字符,所以这个参数输入0-2结果都一样
ss = '12345678987654321'
{{ ss|truncatechars:'10' }}
-----------------------------
1234567...

# truncatewords过滤器,过滤单词,是按照空格分的
ss = '123 456 789 876 543 21'
{{ ss|truncatewords:'2' }}
-------------------------------
123 456 ...

五、标签

常用标签包括for,for ... empty,if,with,csrf_token

# views.py
def index(request):
    ll=['lqz','yang','zs','ls','ww']
    dic={'name':'yang','age':19}
    count=1
    lqzisnbplus='yang'
    b=True
    user_list=[{'name':'name1','age':19},{'name':'name2','age':18},{'name':'name3','age':22},{'name':'name4','age':99},{'name':'name5','age':18},{'name':'name6','age':18}]
    return render(request, 'index.html', locals())

1.for标签与for...empty标签

用法:{% 标签名 %}

标签for,在标签for的内部一直有一个forloop对象,是个字典
counter0:从0开始,每循环一次加1
counter:从1开始,每循环一次加1
revcounter:从列表长度开始,每循环一次减一
first:判断是不是循环的第一个
last:判断是不是循环的最后一个
parentloop:父级forloop对象(for循环嵌套)
{'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False}
<h2>for的用法</h2>
{% for l in ll %}
    {# <p>{{ l }}</p> #}
    <p><a href="http://127.0.0.1:8080/{{ l }}">{{ l }}</a></p>
{% endfor %}

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

<hr>
<h2>for ----empty的用法</h2>
<ul>
    {% for l in ll %}
        <li>{{ l }}</li>
    {% empty %}
        <li>没有数据</li>
    {% endfor %}
</ul>

<h2>forloop对象</h2>
{% for dic in user_list %}

    {% for key,value in dic.items %}
        {{ forloop.parentloop.counter }}
        <p>{{ key }}:{{ value }}</p>
    {% endfor %}

{% endfor %}

2.if标签

<h2>if</h2>

{% if b %}
    <p>b是true的</p>
{% else %}
    <p>b是false的</p>
{% endif %}

3.with标签

with标签主要是起别名

{% with forloop.parentloop.counter as aaa %}
    {{ aaa }}
{% endwith %}


{% with lqzisnbplus as a %}
{{ a }}
----{{ lqzisnbplus }}

{% endwith %}

4.csrf标签

<h2>csrf</h2>

{% csrf_token %}
<input type="text" name="csrfmiddlewaretoken" value="uC35XuP1J2Va74ArYiNw4TMZ0PaZ6V4qvVGCsUQcqiKF5Sr8IrWS0rzpmOmPBrjY">
</body>

六、自定义标签和过滤器

1.自定义过滤器

@register.filter可以加括号,加括号可以传一个safe=True的参数,设置了之后在视图函数中就不需要再使用mark_safe函数了。但是对于装饰器来说,加了括号其实是运行了,只是对于我们的这个装饰器来说,加不加都可以

"""
第一步:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag
第二步:在app中创建templatetags包(包名只能是templatetags,不能改)
第三步:在包内,新建py文件(如:my_tags.py)
第四步:写代码(过滤器)
"""
from django import template
register = template.Library()


@register.filter
def my_upper(value):
	return value.upper()

# 第五步使用:(在模板中),先load,再使用

{% load my_tags %}
{{ 'aa'|my_upper }}

2.自定义标签

"""
第一步:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag
第二步:在app中创建templatetags包(包名只能是templatetags,不能改)
第三步:在包内,新建py文件(如:my_tags.py)
第四步:写代码(过滤器)
"""
from django import template
register = template.Library()

@register.simple_tag
def my_csrf():
	import uuid
	res=uuid.uuid4()
	return mark_safe('<input type="hidden" name="csrfmiddlewaretoken" value="%s">'%res)

# 第五步使用:(模板),先load,再使用
{% load my_tags %}
{% my_csrf %}
{% my_tag 1 3 4 %}  # 传参数直接在后面加,用空格分隔	

七、inclusion_tag的使用

inclusion_tag实现了代码和html的分离,对于前端页面,我们只需要调用需要的标签,就能连带把这个标签绑定的html显示出来。在下面的例子中可以看到,在index.html页面上,完全没有html代码。但是依然能够渲染出页面。

"""
可以生成一片模板中的代码块
第一步:在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag
第二步:在app中创建templatetags包(包名只能是templatetags,不能改)
第三步:在包内,新建py文件(如:my_tags.py)
第四步:写代码(inclusion_tag)
"""
from django import template
register = template.Library()

# inclusion_tag,传一个模板文件
@register.inclusion_tag('left.html')
def left(num):
	dic = {i: '第%s页' % i for i in range(num)}
	# 固定返回的必须是字典
	return {'data': dic}

@register.inclusion_tag('beautiful.html')
def beautiful(title, url):
	return {'title': title, 'url': url}
    
# 第五步使用:(在模板中),先load,再使用
{% load my_tags %}
{% left 5%}
{% beautiful '名字' '地址'%}
        
        
# 它跟tag有什么不同?
	-tag需要在代码中写html的东西
    -inclusion_tag代码跟模板分离
left.html
{% for key,value in data.items %}
{#    <p><a href="http://127.0.0.1:8000/{{ key }}">{{ value }}</a></p>#}
    <p>key是:{{ key }}   value是:{{ value }}</p>
{% endfor %}


beautiful.html
<div class="panel panel-danger">
    <div class="panel-heading">
        <h3 class="panel-title">{{ title }}</h3>
    </div>
    <div class="panel-body">
        详情点击:<a href="{{url}}">疯狂点我</a>
    </div>
</div>
index.html

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


{% load my_tags %}
{% left 10 %}

<hr>
{% beautiful '同性交友' 'http://www.github.com' %}

<hr>
{% beautiful '异性交友' 'http://www.cnblogs.com' %}

<hr>
{% tab_beautiful 'xxx' 'http://www.cnblogs.com'%}
</body>
</html>

八、模板的导入和继承

都是为了减少代码冗余

模板导入和继承的本质,其实就是打开了两个文件,然后在相应地方直接替换

1.模板导入

# 第一步:新建一个 xx.html,把好看的模板写入,只需要写入部分就行了,不需要把什么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>
# 第二步:在你想用的地方
{% include 'xx.html' %}   	

2.模板继承

# 第一步:写一个母版,写空盒子,这里需要写一个完整的页面,然后在部分区域留空白,在空白地方写下面代码
{% block top %}
            
{% endblock %}

# 第二步:某个页面要使用母版,引入,扩写盒子
{% extends 'base.html' %}
{% block top %}
	index页面代码
{% endblock %}

具体例子

母版,base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
    {% block css %}

    {% endblock %}
    <title>
        {% block title %}
        
        {% endblock %}
    </title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="top" style="height: 200px;background-color: #1b6d85">
            {% block top %}
            
            {% endblock %}
        </div>
        <div class="body" style="height: 600px">
            <div class="col-md-3" style="height: 600px;background-color: yellow">
               {% include 'beautiful_egon.html' %}
                <hr>
                {% include 'beautiful_egon.html' %}
            </div>
            <div class="col-md-9" style="height: 600px;background-color: red">
                {% block content %}
                
                {% endblock %}
            </div>
        </div>
        <div class="footer" style="height: 200px;background-color: #4cae4c">
            <img src="{% get_static_prefix %}img/1.jpg" height="60"  width="60" alt="">
        </div>
    </div>
</div>

</body>
</html>

继承的页面,order.html

{% extends 'base.html' %}

{% block title %}
order页面
{% endblock %}

{% block content %}
<h1>我是order页面</h1>
{% endblock %}

{% block top %}
<h1>我是order页面的头</h1>
{% endblock %}

九、引入静态文件方式

第一种:
/static/sdsa/sdfasdf.jpg
第二种:
{% load static %}
{% static 参数(路径)%}
第三种:
{% load static %}
src='{%get_static_prefiex %}拼路径'


第一种举例: <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 "images/hi.jpg" as myphoto %}
     <img src="{{ myphoto }}"></img>
    
    {% load static %}
	{% get_static_prefix as static %}
	<img src="{{ static }}images/hi.jpg" alt="Hi!" />
原文地址:https://www.cnblogs.com/chiyun/p/14066522.html