Django------ The template 模版高级进阶2 2012.08.31

Automatic HTML Escaping----------->

    user-submitted data shouldn't be trusted blindly and inserted directly into your Webpage, because a malicious user could use thin kind of hole to do potentially bad things, This type of security exploit is called a Cross site scipting(XSS) attack.

    Consider this template fragment:

Hello, {{ name }}

    if the name is:

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

    With this name value , the template would be rendered as:

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

    It means the browser wolud pop-up a JavaScript alert box!

    Similar, what if the name contained a '<' symbol, like this:

<b>username

    That would result in a rendered template like this :

Hello, <b>username

    In turn, would result in the remainder of the wep page being bolded!

 

    To avoid this problem, you have two options:

    One, you can make sure to run each untrusted variable through the escape filter, which converts potentially harmful HTML characters to unharmful ones. This was the default solution in Django for its first few years, but the problem is that it puts the onus on you, the developer / template author, to ensure you’re escaping everything. It’s easy to forget to escape data.
    Two, you can take advantage of Django’s automatic HTML escaping. The remainder of this section describes how auto-escaping works.

    By default in Django, every template automatically escapes the output of every variable tag. Specifically, these five characters are escaped:

< is converted to &lt;
> is converted to &gt;
' (single quote) is converted to &#39;
" (double quote) is converted to &quot;
& is converted to &amp;

    We stress that this behavior is on by default, if you are using Django's template system, you're protected.

    How to Turn it off?  Because sometimes ,template variables contain data that you intender tobe rendered as raw HTML, in which case you do not want their contents to be escaped .For example, you might be using Django's template system to produce text that is not HTML like an e-mail message, for instance.

   For Individual Variables: use the safe filter:

This will be escaped: {{data}}
This will not be escaped:{{data|safe}}
If the data contains '<b>' The out put will be 

This will be escaped: &lt;b&gt;
This will not be escaped: <b>

   For Template Blocks use:

{% autoescape off%}
    hello {{name}}
{% endautoescape %}
The autoescape tag takes either on or off as its argument. At times, you might want to force auto-escaping when it would otherwise be disabled. Here is an example template:1

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 %}
The auto-escaping tag passes its effect on to templates that extend the current one as well as templates included via the include tag, just like all block tags. For example:

# 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 %}
Because auto-escaping is turned off in the base template, it will also be turned off in the child template, resulting in the following rendered HTML when the greeting variable contains the string <b>Hello!</b>:

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

 

Inside Template Loading---------->

    Generally, you will store templates in files on your filesystem, but you can use custom template loaders to load templates from other source.

    Django has two ways to load templates:

  • django.template.loader.get_template(template_name): returns the compiled template (a template object) for the template with the given name, If the template does not exist, a TemplateDoesNotExise exception will be raised.
  • django.template.loader.select_template(template_name_list):it is just like get_template, except it takes a list of templatenames. of the list, Of the list, it returns the first template that exists. If none of the templates exist, a TemplateDoesNotExist exception will be raised.

    Some of loaders are disabled by default, but you can activate them by editing the TEMPLATE_LOADERS setting. It should be a tuple of strings, where each string represents a template loader.These template loaders ship with Django:

django.template.loaders.filesystem.load_template_source: This loader loads templates from the filesystem, according to TEMPLATE_DIRS. It is enabled by default.

django.template.loaders.app_directories.load_template_source: This loader loads templates from Django applications on the filesystem. For each application in INSTALLED_APPS, the loader looks for a templates subdirectory. If the directory exists, Django looks for templates there.

This means you can store templates with your individual applications, making it easy to distribute Django applications with default templates. For example, if INSTALLED_APPS contains ('myproject.polls', 'myproject.music'), then get_template('foo.html') will look for templates in this order:

/path/to/myproject/polls/templates/foo.html
/path/to/myproject/music/templates/foo.html
Note that the loader performs an optimization when it is first imported: it caches a list of which INSTALLED_APPS packages have a templates subdirectory.

This loader is enabled by default.
django.template.loaders.eggs.load_template_source: This loader is just like app_directories, except it loads templates from Python eggs rather than from the filesystem. This loader is disabled by default; you’ll need to enable it if you’re using eggs to distribute your application. (Python eggs are a way of compressing Python code into a single file.)

    Django uses the template loaders in order according to the TEMPLATE_LOADERS setting. It uses each loader until a loader finds a match.

 

Extending the Template system:How to extend the system with custom code-------->

    Most template customization comes in the form of custom template tags and filters, Although eht Django template language comes with many built-in tags and filters, you will probably assemble your own libraries of tags and filters that fit your own needs, Fortunately, It's quite easy to define your own functionality.

    Creating a templtate library====>

    The first thing to do is create a template library, a small bit of infrastructure Django can hook into.(一个小一点的基础设施django可以勾进的).

    Creating a template library is a two-step process:

  • First, decide which django application should house the template library, If you have created an app via manage.py startapp, you can put in there, you can also create another app solely for the template library, We'd recommend teh latter, because your filters might be useful to you in future projects.make sure to add the app to your INSTALLED_APPS setting.
  • Second, create a templatetags directory in the appropriate Django application's package.It  should be on the same level as models.py views.py and so forth .For examle:
books/
    __init__.py
    models.py
    templatetags/
    views.py

    Create two empty files in the templatetags directory:an  __init__.py file(to indicate to the python that this is a package containing Python code)and a file will contain your custom tag/filter definitions. The name of the latter file is what you will use to load the tags later, For example, If your custom tags/filters are in a file called poll_extras.py, you'd write the following in a template:

{% load poll_extras %}

    The {% load %} tag looks at your INSTALLED_APPS setting and only allows the loading of template libraries within installed django applications, This is a security feature; it allows you to host Python code for many template libraries on a single computer without enabling access to all of them for every django installation.   

   If you write a template library that is not tied to any particular model/views, it's valid and quite normal to have a django application package that contains only a templatetags package, There;s no limit on how many modules you put int the templatetags package, Just keep in mind that a {% load %} statement will load tags/filters for teh fiven Python module name, not name of the application.

   Once you have create that python module ,you will just have to write a bit of python  code, depending on whether you are writing filters or tags.

    To be a valid tag library, the module must contain a module-lever variable named refister that is an instance of template.Library, This is the data structure in which all tags and filters are registered so, near the top of your module, inser the following:(模块需要一个包含名字register的模块级变量,这个变量是template.Library 的实例),是所有注册标签和过滤器的数据结构。)

from django import template

register = template.Library()

    Once you've created this register variable, you'll use it to create template filters and tags.  

    Writing Custom Template Filters=========>

    Custom filters are just Python functions that take one or two arguments:(参数)

  • The value of the variable(input)
  • The value of the argument, which can have a default value or be left out altogether.

    For example, in the filter{{ var|foo:"bar"}}, the filter foo would be passed contents of the variable var and the argument "bar".

    Filter functions should always return something. They shouldn’t raise exceptions, and they should fail silently. If there’s an error, they should return either the original input or an empty string, whichever makes more sense.(过滤函数应该返回一些东西,他们不应该抛出异常,他们应该静默失败。)

     Here is an example filter definition:

def cut(value, arg):
    "Removes all values of arg from the given string"
    return value.replace(arg, '')

    And here's an example of how that filter would be used to cut space from a varible's value:

{{ somevariable | cut:" "}}

    Most filters do not take argument, In this case, just leave the argument out of your function

def lower(value);
    return value.lower()

    When you've written your filter definition, you need to register it with your Library instancem to make it available to django's template language:

register.filter('cut', cut)
register.filter('lower', lower)

    The Library.filter() method takes two arguments:

  • The name of the filter 
  • The filter function itself

    If you're using python2.4 or above, you can use register.filter() as a decorator instead( 装饰器)

@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg,'')

@refister.filter
def lower(value):
    return value.lower()

    If you leave the name argument, as in the second example, Django will use the function;s name as the filter name.

    Here is a complete template library example, supplying the cut filter:

from django import template

register = template.Library()

@register.filter(name='cut')
def cut(value, arg):
    return value.replace(arg, '')

    Write Custom Template Tags==================>

    Tags are more complex than filters, because tags can do nearly angthing.

    Template system works in a two-step process:compiling and rendering. To define a custom template tag, you need to tell django how to manage both of these step when it gets to your tag.

    When django compiles a template, it splits the raw template text into nodes. Each node is an instance of django.template.Node and has a render() method. Thus, a compiled template is simply a list of Node objects. For example consider this template:

Hello, {{ person.name }}.

{% ifequal name.birthday today %}
    Happy birthday!
{% else %}
    Be sure to come back on your birthday.
{% endifequal %}

    In compiled template form, this template is represented as this list of nodes:

  • Text node: "Hello"
  • Variable node: person.name
  • Text node: ".\n\n"
  • Ifeaual node:name.birthday and today

    When you call render() on a compiled template, the template calls render() on each Node in its node list, with the given context, The result are all concatenated together to form the output of the template, Thus, to define a custom template tag, you specify how the raw template tag is convertd into a Node and what the node's render()method does.(当你调用一个已经编译的模版的render()方法时候,模版就会用给丁的context来调用每个在它的节点列表上的所有节点的render()方法。这些渲染的结果合并起来,形成了模版的输出,因此,要自定义模版标签,需要指明原始模版标签如何转换成节点,和节点的render方法的功能)

    In the sections that follow, we cover all the steps in writing a custom tag.

 

编写编译函数

    当遇到一个模版标签(template tag)时,模版解释器就会把标签包含的内容,以及模版解释器自己作为参数调用一个Python函数,这个函数负责返回一个和当前模版标签内容相对应的节点的实例。

posted @ 2012-08-31 16:31  事件轮询,回不到过去  阅读(574)  评论(0编辑  收藏  举报