Django之模板Template

模板介绍

  • 作为Web框架,Django提供了模板,可以很便利的动态生成HTML
  • 模版系统致力于表达外观,而不是程序逻辑
  • 模板的设计实现了业务逻辑(view)与显示内容(template)的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用
  • 模板包含
    • HTML的静态部分
    • 动态插入内容部分
  • Django模板语言,简写DTL,定义在django.template包中
  • 由startproject命令生成的settings.py定义关于模板的值:
    • DIRS定义了一个目录列表,模板引擎按列表顺序搜索这些目录以查找模板源文件
    • APP_DIRS告诉模板引擎是否应该在每个已安装的应用中查找模板
  • 常用方式:在项目的根目录下创建templates目录,设置DIRS值

    DIRS=[os.path.join(BASE_DIR,"templates")]

    模板处理

  • Django处理模板分为两个阶段
  • Step1 加载:根据给定的标识找到模板然后预处理,通常会将它编译好放在内存中

    loader.get_template(template_name),返回一个Template对象
  • Step2 渲染:使用Context数据对模板插值并返回生成的字符串

    Template对象的render(RequestContext)方法,使用context渲染模板
  • 加载渲染完整代码:

    from django.template import loader, RequestContext
    from django.http import HttpResponse
    
    def index(request):
        tem = loader.get_template(‘temtest/index.html‘)
        context = RequestContext(request, {})
        return HttpResponse(tem.render(context))

    快捷函数

  • 为了减少加载模板、渲染模板的重复代码,django提供了快捷函数
  • render_to_string("")
  • render(request,‘模板‘,context)

    from django.shortcuts import render
    
    def index(request):
        return render(request, ‘temtest/index.html‘)

    定义模板

  • 模板语言包括
    • 变量
    • 标签 { % 代码块 % }
    • 过滤器
    • 注释{# 代码或html #}

    变量

语法:

{{ variable }}
  • 当模版引擎遇到一个变量,将计算这个变量,然后将结果输出
  • 变量名必须由字母、数字、下划线(不能以下划线开头)和点组成
  • 当模版引擎遇到点("."),会按照下列顺序查询:
    1. 字典查询,例如:foo["bar"]
    2. 属性或方法查询,例如:foo.bar
    3. 数字索引查询,例如:foo[bar]
  • 如果变量不存在, 模版系统将插入‘‘ (空字符串)
  • 在模板中调用方法时不能传递参数

在模板中调用对象的方法

  • 在models.py中定义类HeroInfo

    from django.db import models
    
    class HeroInfo(models.Model):
        ...
        def showName(self):
            return self.hname
  • 在views.py中传递HeroInfo对象

    from django.shortcuts import render
    from models import *
    
    def index(request):
        hero = HeroInfo(hname=‘abc‘)
        context = {‘hero‘: hero}
        return render(request, ‘temtest/detail.html‘, context)
  • 在模板detail.html中调用

    {{hero.showName}}

    标签

  • 语法:{ % tag % }
  • 作用
  • 在输出中创建文本
  • 控制循环或逻辑
  • 加载外部信息到模板中供以后的变量使用
  • for标签

    { %for ... in ...%}
    循环逻辑
    {{forloop.counter}}表示当前是第几次循环
    { %empty%}
    给出的列表为或列表不存在时,执行此处
    { %endfor%}
  • if标签

    { %if ...%}
    逻辑1
    { %elif ...%}
    逻辑2
    { %else%}
    逻辑3
    { %endif%}
  • comment标签

    { % comment % }
    多行注释
    { % endcomment % }
  • include:加载模板并以标签内的参数渲染

    { %include "foo/bar.html" % }
  • url:反向解析

    { % url ‘name‘ p1 p2 %}
  • csrf_token:这个标签用于跨站请求伪造保护

    { % csrf_token %}
  • 布尔标签:and、or,and比or的优先级高
  • block、extends:详见“模板继承”
  • autoescape:详见“HTML转义”

    过滤器

  • 语法:{ { 变量|过滤器 }},例如{ { name|lower }},表示将变量name的值变为小写输出
  • 使用管道符号 (|)来应用过滤器
  • 通过使用过滤器来改变变量的计算结果
  • 可以在if标签中使用过滤器结合运算符

    if list1|length > 1
  • 过滤器能够被“串联”,构成过滤器链

    name|lower|upper
  • 过滤器可以传递参数,参数使用引号包起来

    list|join:", "
  • default:如果一个变量没有被提供,或者值为false或空,则使用默认值,否则使用变量的值

    value|default:"什么也没有"
  • date:根据给定格式对一个date变量格式化

    value|date:‘Y-m-d‘
  • escape:详见“HTML转义”
  • 点击查看详细的过滤器

    注释

  • 单行注释

    {#...#}
  • 注释可以包含任何模版代码,有效的或者无效的都可以

    {# { % if foo % }bar{ % else % } #}
  • 使用comment标签注释模版中的多行内容

    示例
    查询所有英雄信息显示出来,要求奇数行显示为红色,偶数行显示为蓝色

    模板继承

  • 模板继承可以减少页面内容的重复定义,实现页面内容的重用
  • 典型应用:网站的头部、尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义
  • block标签:在父模板中预留区域,在子模板中填充
  • extends继承:继承,写在模板文件的第一行
  • 定义父模板base.html

    { %block block_name%}
    这里可以定义默认值
    如果不定义默认值,则表示空字符串
    { %endblock%}
  • 定义子模板index.html

    { % extends "base.html" %}
  • 在子模板中使用block填充预留区域

    { %block block_name%}
    实际填充内容
    { %endblock%}

    说明

  • 如果在模版中使用extends标签,它必须是模版中的第一个标签
  • 不能在一个模版中定义多个相同名字的block标签
  • 子模版不必定义全部父模版中的blocks,如果子模版没有定义block,则使用了父模版中的默认值
  • 如果发现在模板中大量的复制内容,那就应该把内容移动到父模板中
  • 使用可以获取父模板中block的内容
  • 为了更好的可读性,可以给endblock标签一个名字

    { % block block_name %}
    区域内容
    { % endblock block_name %}

    三层继承结构

  • 三层继承结构使代码得到最大程度的复用,并且使得添加内容更加简单
  • 如下图为常见的电商页面

1.创建根级模板

  • 名称为“base.html”
  • 存放整个站点共用的内容

    <!DOCTYPE html>
    <html>
    <head>
        <title>{%block title%}{%endblock%} 水果超市</title>
    </head>
    <body>
    top--{{logo}}
    <hr/>
    {%block left%}{%endblock%}
    {%block content%}{%endblock%}
    <hr/>
    bottom
    </body>
    </html>

    2.创建分支模版

  • 继承自base.html
  • 名为“base_*.html”
  • 定义特定分支共用的内容
  • 定义base_goods.html

    {%extends ‘temtest/base.html‘%}
    {%block title%}商品{%endblock%}
    {%block left%}
    <h1>goods left</h1>
    {%endblock%}
  • 定义base_user.html

    {%extends ‘temtest/base.html‘%}
    {%block title%}用户中心{%endblock%}
    {%block left%}
    <font color=‘blue‘>user left</font>
    {%endblock%}
  • 定义index.html,继承自base.html,不需要写left块

    {%extends ‘temtest/base.html‘%}
    {%block content%}
    首页内容
    {%endblock content%}

    3.为具体页面创建模板,继承自分支模板

  • 定义商品列表页goodslist.html

    {%extends ‘temtest/base_goods.html‘%}
    {%block content%}
    商品正文列表
    {%endblock content%}
  • 定义用户密码页userpwd.html

    {%extends ‘temtest/base_user.html‘%}
    {%block content%}
    用户密码修改
    {%endblock content%}

    4.视图调用具体页面,并传递模板中需要的数据

  • 首页视图index

    logo=‘welcome to itcast‘
    def index(request):
        return render(request, ‘temtest/index.html‘, {‘logo‘: logo})
  • 商品列表视图goodslist

    def goodslist(request):
        return render(request, ‘temtest/goodslist.html‘, {‘logo‘: logo})
  • 用户密码视图userpwd

    def userpwd(request):
        return render(request, ‘temtest/userpwd.html‘, {‘logo‘: logo})

    5.配置url

    from django.conf.urls import url
    from . import views
    urlpatterns = [
        url(r‘^$‘, views.index, name=‘index‘),
        url(r‘^list/$‘, views.goodslist, name=‘list‘),
        url(r‘^pwd/$‘, views.userpwd, name=‘pwd‘),
    ]

    HTML转义

  • Django对字符串进行自动HTML转义,如在模板中输出如下值:

    视图代码:
    def index(request):
        return render(request, ‘temtest/index2.html‘,
                      {
                          ‘t1‘: ‘<h1>hello</h1>‘
                      })
    模板代码:
    {{t1}}
  • 显示效果如下图:

会被自动转义的字符

  • html转义,就是将包含的html标签输出,而不被解释执行,原因是当显示用户提交字符串时,可能包含一些攻击性的代码,如js脚本
  • Django会将如下字符自动转义:

    < 会转换为&lt;
    
    > 会转换为&gt;
    
    ‘ (单引号) 会转换为'
    
    " (双引号)会转换为 &quot;
    
    & 会转换为 &amp;
  • 当显示不被信任的变量时使用escape过滤器,一般省略,因为Django自动转义

    {{t1|escape}}

    关闭转义

  • 对于变量使用safe过滤器

    {{ data|safe }}
  • 对于代码块使用autoescape标签

    { % autoescape off %}
    {{ body }}
    { % endautoescape %}
  • 标签autoescape接受on或者off参数
  • 自动转义标签在base模板中关闭,在child模板中也是关闭的

字符串字面值

  • 手动转义

    { { data|default:"<b>123</b>" }}
  • 应写为

    { { data|default:"&lt;b&gt;123&lt;/b&gt;" }}

    csrf

  • 全称Cross Site Request Forgery,跨站请求伪造
  • 某些恶意网站上包含链接、表单按钮或者JavaScript,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站上完成某些操作,这就是跨站攻击
  • 演示csrf如下
  • 创建视图csrf1用于展示表单,csrf2用于接收post请求

    def csrf1(request):
        return render(request,‘booktest/csrf1.html‘)
    def csrf2(request):
        uname=request.POST[‘uname‘]
        return render(request,‘booktest/csrf2.html‘,{‘uname‘:uname})
  • 配置url

    url(r‘^csrf1/$‘, views.csrf1),
    url(r‘^csrf2/$‘, views.csrf2),
  • 创建模板csrf1.html用于展示表单

    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <form method="post" action="/crsf2/">
        <input name="uname"><br>
        <input type="submit" value="提交"/>
    </form>
    </body>
    </html>
  • 创建模板csrf2用于展示接收的结果

    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    {{ uname }}
    </body>
    </html>
  • 在浏览器中访问,查看效果,报错如下:

  • 将settings.py中的中间件代码‘django.middleware.csrf.CsrfViewMiddleware‘注释
  • 查看csrf1的源代码,复制,在自己的网站内建一个html文件,粘贴源码,访问查看效果

防csrf的使用

  • 在django的模板中,提供了防止跨站攻击的方法,使用步骤如下:
  • step1:在settings.py中启用‘django.middleware.csrf.CsrfViewMiddleware‘中间件,此项在创建项目时,默认被启用
  • step2:在csrf1.html中添加标签

    <form>
    {% csrf_token %}
    ...
    </form>
  • step3:测试刚才的两个请求,发现跨站的请求被拒绝了,效果如下图

取消保护

  • 如果某些视图不需要保护,可以使用装饰器csrf_exempt,模板中也不需要写标签,修改csrf2的视图如下

    from django.views.decorators.csrf import csrf_exempt
    
    @csrf_exempt
    def csrf2(request):
        uname=request.POST[‘uname‘]
        return render(request,‘booktest/csrf2.html‘,{‘uname‘:uname})
  • 运行上面的两个请求,发现都可以请求

保护原理

  • 加入标签后,可以查看源代码,发现多了如下代码

    <input type=‘hidden‘ name=‘csrfmiddlewaretoken‘ value=‘nGjAB3Md9ZSb4NmG1sXDolPmh3bR2g59‘ />
  • 在浏览器的调试工具中,通过network标签可以查看cookie信息
  • 本站中自动添加了cookie信息,如下图

  • 查看跨站的信息,并没有cookie信息,即使加入上面的隐藏域代码,发现又可以访问了
  • 结论:django的csrf不是完全的安全
  • 当提交请求时,中间件‘django.middleware.csrf.CsrfViewMiddleware‘会对提交的cookie及隐藏域的内容进行验证,如果失败则返回403错误

验证码

  • 在用户注册、登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻一些服务器的压力
  • 使用验证码也是一种有效的防止crsf的方法
  • 验证码效果如下图:

验证码视图

  • 新建viewsUtil.py,定义函数verifycode
  • 此段代码用到了PIL中的Image、ImageDraw、ImageFont模块,需要先安装Pillow(3.4.1)包,详细文档参考http://pillow.readthedocs.io/en/3.4.x/
  • Image表示画布对象
  • ImageDraw表示画笔对象
  • ImageFont表示字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”
  • 代码如下:
    from django.http import HttpResponse
    def verifycode(request):
        #引入绘图模块
        from PIL import Image, ImageDraw, ImageFont
        #引入随机函数模块
        import random
        #定义变量,用于画面的背景色、宽、高
        bgcolor = (random.randrange(20, 100), random.randrange(
            20, 100), 255)
        width = 100
        height = 25
        #创建画面对象
        im = Image.new(‘RGB‘, (width, height), bgcolor)
        #创建画笔对象
        draw = ImageDraw.Draw(im)
        #调用画笔的point()函数绘制噪点
        for i in range(0, 100):
            xy = (random.randrange(0, width), random.randrange(0, height))
            fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
            draw.point(xy, fill=fill)
        #定义验证码的备选值
        str1 = ‘ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0‘
        #随机选取4个值作为验证码
        rand_str = ‘‘
        for i in range(0, 4):
            rand_str += str1[random.randrange(0, len(str1))]
        #构造字体对象
        font = ImageFont.truetype(‘FreeMono.ttf‘, 23)
        #构造字体颜色
        fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
        #绘制4个字
        draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
        draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
        draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
        draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
        #释放画笔
        del draw
        #存入session,用于做进一步验证
        request.session[‘verifycode‘] = rand_str
        #内存文件操作
        import cStringIO
        buf = cStringIO.StringIO()
        #将图片保存在内存中,文件类型为png
        im.save(buf, ‘png‘)
        #将内存中的图片数据返回给客户端,MIME类型为图片png
        return HttpResponse(buf.getvalue(), ‘image/png‘)

    配置url

  • 在urls.py中定义请求验证码视图的url

    from . import viewsUtil
    
    urlpatterns = [
        url(r‘^verifycode/$‘, viewsUtil.verifycode),
    ]

    显示验证码

  • 在模板中使用img标签,src指向验证码视图

    <img id=‘verifycode‘ src="/verifycode/" alt="CheckCode"/>
  • 启动服务器,查看显示成功
  • 扩展:点击“看不清,换一个”时,可以换一个新的验证码

    <script type="text/javascript" src="/static/jquery-1.12.4.min.js"></script>
    <script type="text/javascript">
        $(function(){
            $(‘#verifycodeChange‘).css(‘cursor‘,‘pointer‘).click(function() {
                $(‘#verifycode‘).attr(‘src‘,$(‘#verifycode‘).attr(‘src‘)+1)
            });
        });
    </script>
    <img id=‘verifycode‘ src="/verifycode/?1" alt="CheckCode"/>
    <span id=‘verifycodeChange‘>看不清,换一个</span>
  • 为了能够实现提交功能,需要增加form和input标签

    <form method=‘post‘ action=‘/verifycodeValid/‘>
        <input type="text" name="vc">
        <img id=‘verifycode‘ src="/verifycode/?1" alt="CheckCode"/>
    <span id=‘verifycodeChange‘>看不清,换一个</span>
    <br>
    <input type="submit" value="提交">
    </form>

    验证

  • 接收请求的信息,与session中的内容对比

    from django.http import HttpResponse
    
    def verifycodeValid(request):
        vc = request.POST[‘vc‘]
        if vc.upper() == request.session[‘verifycode‘]:
            return HttpResponse(‘ok‘)
        else:
            return HttpResponse(‘no‘)
  • 配置验证处理的url

    urlpatterns = [
        url(r‘^verifycodeValid/$‘, views.verifycodeValid),
    ]

    第三方

  • 可以在网上搜索“验证码”,找到一些第三方验证码提供网站,阅读文档,使用到项目中

原文地址:https://www.cnblogs.com/alexzhang92/p/9315286.html

时间: 2024-11-08 18:03:04

Django之模板Template的相关文章

Django[11]模板Template context和Bootstrap使用

视图views.py中: 1234567891011121314151617181920212223242526 from __future__ import unicode_literals from django.shortcuts import render # Create your views here.from django.http import HttpResponse def (request): context = { "title": "home&quo

django MTV模板template(T)

在上一章节中我们使用 django.http.HttpResponse() 来输出 " meishiweb!".该方式将数据与视图混合在一起,不符合 Django 的 MTV 思想. 下面我们将为大家详细介绍 Django 模板的应用,模板是一个文本,用于分离文档的表现形式和内容.

Django框架简介及模板Template

Django框架简介 MVC框架和MTV框架 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器(Controller),具有耦合性低.重用性高.生命周期成本低等优点. 想要更详细的了解MVC模式? >> 点我 Django框架的设计模式借鉴了MVC框架的思想,也是分成三部分,来降低各个部分之间的耦合性. Django框架的不同之处在于它拆分的三部分为:Model(模型).Templ

Django的模板系统

模板系统介绍 模板系统的组成:HTML代码和逻辑控制代码 逻辑控制代码可以理解是django模板语言 django的模板语言组成 变量(使用双大括号来引用变量): 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag) 模板继承 模板语言之变量 语法: {{var_name}} var_name 指变量名 使用模板语言之前: 先介绍template对象和Context对象 进入django的项目的交互环境 python manange.py shell >>> from dja

第四章:Django 的模板系统(转)

在之前的章节中,你可能觉得例子中视图返回文本有点不妥.即是, HTML 是直接写在 Python 代码中的. 这种做法会导致这些问题: 要做任何设计上的更改就必须改写 Python 代码.网站的设计风格的更变一般来说会比更改后台的 Ptyhon 代码来得频繁,因此如果能够更改设计而不用更改 Python 变得尤为方便. 2 Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成.设计人员和 HTML/CSS 编写人员都不应

Django 自定义模板标签和过滤器

1.创建一个模板库 使用模板过滤器的时候,直接把过滤器写在app里,例如:在app里新建一个templatetags的文件夹,这个目录应当和 models.py . views.py 等处于同一层次.例如: books/     __init__.py     models.py     templatetags/     views.py 在 templatetags 中创建两个空文件:一个 __init__.py (告诉Python这是一个包含了Python代码的包)和一个用来存放你自定义的

Django框架模板详解

Django模板详解 模板使用 模板基本由两个部分组成,一是HTML代码,二是逻辑控制代码. 逻辑控制的实现又基本由三个部分组成: 1. 变量的使用 {{ person_name }} #使用双大括号来引用变量 2. tag的使用 {% if ordered_warranty %} #使用大括号和百分号的组成来表示使用Django提供的 template tag {% for item in item_list %} <li>{{ item }}</li> {% endfor %}

实习生的Django[2](模板)

快要下班了,今天研究了一整天日文翻译(我的项目与日文息息相关阿),累得要死,在下班之前偷偷总结一下今天学的Django. 因为不能花很多时间去学Django,要均衡-所以今天就之做了一下模板. 因为上一次写的[1]说的视图,今天很自然就开始作模板了. 什么叫模板? 玩过C++的人都知道(c++三宝:template,stl,class),但是为了博文看起来好像作者有在写,我就用简单地话解释一下:我们面试都非常讨厌自我介绍(好像面试官不会看简历的样子?),为此我只能将:我叫XXX,来自XXX,特长

python django -4 模板

模板介绍 作为Web框架,Django提供了模板,可以很便利的动态生成HTML 模版系统致力于表达外观,而不是程序逻辑 模板的设计实现了业务逻辑(view)与显示内容(template)的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用 模板包含 HTML的静态部分 动态插入内容部分 Django模板语言,简写DTL,定义在django.template包中 由startproject命令生成的settings.py定义关于模板的值: DIRS定义了一个目录列表,模板引擎按列表顺序