在Django框架中编写Context处理器的方法

yipeiwu_com5年前Python基础

写Context处理器的一些建议

编写处理器的一些建议:

    使每个context处理器完成尽可能小的功能。 使用多个处理器是很容易的,所以你可以根据逻辑块来分解功能以便将来复用。

    要注意 TEMPLATE_CONTEXT_PROCESSORS 里的context processor 将会在基于这个settings.py的每个 模板中有效,所以变量的命名不要和模板的变量冲突。 变量名是大小写敏感的,所以processor的变量全用大写是个不错的主意。

    不论它们存放在哪个物理路径下,只要在你的Python搜索路径中,你就可以在 TEMPLATE_CONTEXT_PROCESSORS 设置里指向它们。 建议你把它们放在应用或者工程目录下名为 context_processors.py 的文件里。

html自动转意

从模板生成html的时候,总是有一个风险——变量包了含会影响结果html的字符。 例如,考虑这个模板片段:

Hello, {{ name }}.

一开始,这看起来是显示用户名的一个无害的途径,但是考虑如果用户输入如下的名字将会发生什么:

<script>alert('hello')</script>

用这个用户名,模板将被渲染成:

Hello, <script>alert('hello')</script>

这意味着浏览器将弹出JavaScript警告框!

类似的,如果用户名包含小于符号,就像这样:

用户名

那样的话模板结果被翻译成这样:

Hello, <b>username

页面的剩余部分变成了粗体!

显然,用户提交的数据不应该被盲目信任,直接插入到你的页面中。因为一个潜在的恶意的用户能够利用这类漏洞做坏事。 这类漏洞称为被跨域脚本 (XSS) 攻击。 关于安全的更多内容,请看20章

为了避免这个问题,你有两个选择:

    一是你可以确保每一个不被信任的变量都被escape过滤器处理一遍,把潜在有害的html字符转换为无害的。 这是最初几年Django的默认方案,但是这样做的问题是它把责任推给你(开发者、模版作者)自己,来确保把所有东西转意。 很容易就忘记转意数据。

    二是,你可以利用Django的自动html转意。 这一章的剩余部分描述自动转意是如何工作的。

在django里默认情况下,每一个模板自动转意每一个变量标签的输出。 尤其是这五个字符。

  •     ``\ ``
  •     System Message: WARNING/2 (<string>, line 491); backlink
  •     Inline literal start-string without end-string.
  •     > 被转换为>
  •     '(单引号)被转换为'
  •     "(双引号)被转换为"
  •     & is converted to &

另外,我强调一下这个行为默认是开启的。 如果你正在使用django的模板系统,那么你是被保护的。
如何关闭它

如果你不想数据被自动转意,在每一站点级别、每一模板级别或者每一变量级别你都有几种方法来关闭它。

为什么要关闭它? 因为有时候模板变量包含了一些原始html数据,在这种情况下我们不想它们的内容被转意。 例如,你可能在数据库里存储了一段被信任的html代码,并且你想直接把它嵌入到你的模板里。 或者,你可能正在使用Django的模板系统生成非html文本,比如一封e-mail。
对于单独的变量

用safe过滤器为单独的变量关闭自动转意:

This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}

你可以把safe当做safe from further escaping的简写,或者当做可以被直接译成HTML的内容。在这个例子里,如果数据包含'',那么输出会变成:

This will be escaped: <b>
This will not be escaped: <b>

对于模板块

为了控制模板的自动转意,用标签autoescape来包装整个模板(或者模板中常用的部分),就像这样:

{% autoescape off %}
 Hello {{ name }}
{% endautoescape %}

autoescape 标签有两个参数on和off 有时,你可能想阻止一部分自动转意,对另一部分自动转意。 这是一个模板的例子:

Auto-escaping is on by default. Hello {{ name }}

{% autoescape off %}
 This will not be auto-escaped: {{ data }}.

 Nor this: {{ other_data }}
 {% autoescape on %}
 Auto-escaping applies again: {{ name }}
 {% endautoescape %}
{% endautoescape %}

auto-escaping 标签的作用域不仅可以影响到当前模板还可以通过include标签作用到其他标签,就像block标签一样。 例如:

# base.html

{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}

# child.html

{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}

由于在base模板中自动转意被关闭,所以在child模板中自动转意也会关闭.因此,在下面一段HTML被提交时,变量greeting的值就为字符串Hello!

<h1>This & that</h1>
<b>Hello!</b>

备注

通常,模板作者没必要为自动转意担心. 基于Pyhton的开发者(编写VIEWS视图和自定义过滤器)只需要考虑哪些数据不需要被转意,适时的标记数据,就可以让它们在模板中工作。

如果你正在编写一个模板而不知道是否要关闭自动转意,那就为所有需要转意的变量添加一个escape过滤器。 当自动转意开启时,使用escape过滤器似乎会两次转意数据,但其实没有任何危险。因为escape过滤器不作用于被转意过的变量。

相关文章

Flask框架路由和视图用法实例分析

本文实例讲述了Flask框架路由和视图用法。分享给大家供大家参考,具体如下: 创建一个简单flask框架程序 #1.导入Flask类 from flask import Flask...

python中的逆序遍历实例

如果你需要遍历数字序列,可以使用内置range()函数。它会生成数列。 range()语法: range(start,end,step=1):顾头不顾尾 正序遍历: range(10):...

Python中如何导入类示例详解

前言 随着我们不断地在一个文件中添加新的功能, 就会使得文件变得很长。 即便使用了继承,也抑制不住类的成长。为了解决这一问题,我们可以将类存储在模块中, 然后在主程序中导入所需的模块,这...

windows下wxPython开发环境安装与配置方法

安装文件准备: 安装文件 下载地址 python-2.6.2.msi http://www.py...

机器学习经典算法-logistic回归代码详解

机器学习经典算法-logistic回归代码详解

一、算法简要 我们希望有这么一种函数:接受输入然后预测出类别,这样用于分类。这里,用到了数学中的sigmoid函数,sigmoid函数的具体表达式和函数图象如下: 可以较为清楚的看到,...