以下代碼節錄自 [url=http://djangobook.com/en/2.0/]Django Book[/url] - Chapter 4 & 9
dynamic path, more flexible and decoupled
locals() trick
It returns a dictionary mapping all local variable names to their values, where “local” means all variables that have been defined within the current scope.
include Template Tag
Template Inheritance
base template
Default TEMPLATE_CONTEXT_PROCESSORS
disable auto-escaping for an individual variable
disable auto-escaping for template block
template loading: TEMPLATE_LOADERS
template loader
[size=large]Extending the Template System[/size]
[b]Writing Custom Template Filters[/b]
Python 2.4 above
[b]Writing Custom Template Tags[/b]
[b]Setting a Variable in the Context[/b]
[b]Setting a Variable in the Context - cleaner solution[/b]
[b]Parsing Until Another Template Tag[/b]
[b]Parsing Until Another Template Tag and Saving Contents[/b]
[i]For more examples of complex rendering, see the source code for {% if %}, {% for %}, {% ifequal %}, and {% ifchanged %}. They live in django/template/defaulttags.py[/i]
[b]Shortcut for Simple Tags[/b]
[b]Inclusion Tags[/b]
[b]Inclusion tags access to values from the parent template’s context[/b]
[b]Writing Custom Template Loaders[/b]
[code="Python"][/code]
# Missing comma!
TEMPLATE_DIRS = (
'/home/django/mysite/templates'
)
dynamic path, more flexible and decoupled
import os.path
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'),
)
locals() trick
It returns a dictionary mapping all local variable names to their values, where “local” means all variables that have been defined within the current scope.
def current_datetime(request):
current_date = datetime.datetime.now()
return render_to_response('current_datetime.html', locals())
include Template Tag
# mypage.html
<html>
<body>
{% include "includes/nav.html" %}
<h1>{{ title }}</h1>
</body>
</html>
# includes/nav.html
<div id="nav">
You are in: {{ current_section }}
</div>
Template Inheritance
base template
# base template
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
{% block content %}{% endblock %}
{% block footer %}
<hr>
<p>Thanks for visiting my site.</p>
{% endblock %}
</body>
</html>
# extend template
{% extends "base.html" %}
{% block title %}The current time{% endblock %}
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
Default TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
)
disable auto-escaping for an individual variable
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
disable auto-escaping for template block
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
template loading: TEMPLATE_LOADERS
django.template.loader.get_template(template_name)
django.template.loader.select_template(template_name_list)
# If the template doesn’t exist, a TemplateDoesNotExist exception will be raised
template loader
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.
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.)
[size=large]Extending the Template System[/size]
[b]Writing Custom Template Filters[/b]
from django import template
register = template.Library()
def cut(value, arg):
"Removes all values of arg from the given string"
return value.replace(arg, '')
def lower(value): # Only one argument.
"Converts a string into all lowercase"
return value.lower()
register.filter('cut', cut)
register.filter('lower', lower)
# in template:
# {{ somevariable|cut:" " }}
Python 2.4 above
from django import template
register = template.Library()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()
[b]Writing Custom Template Tags[/b]
from django import template
register = template.Library()
def do_current_time(parser, token):
try:
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode(format_string[1:-1])
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)
def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)
register.tag('current_time', do_current_time)
# python 2.4 above
@register.tag(name="current_time")
def do_current_time(parser, token):
# ...
[b]Setting a Variable in the Context[/b]
class CurrentTimeNode2(template.Node):
def __init__(self, format_string):
self.format_string = str(format_string)
def render(self, context):
now = datetime.datetime.now()
context['current_time'] = now.strftime(self.format_string)
return ''
# in template:
# {% current_time2 "%Y-%M-%d %I:%M %p" %}
# <p>The time is {{ current_time }}.</p>
[b]Setting a Variable in the Context - cleaner solution[/b]
# in template:
# {% get_current_time "%Y-%M-%d %I:%M %p" as my_current_time %}
# <p>The current time is {{ my_current_time }}.</p>
import re
class CurrentTimeNode3(template.Node):
def __init__(self, format_string, var_name):
self.format_string = str(format_string)
self.var_name = var_name
def render(self, context):
now = datetime.datetime.now()
context[self.var_name] = now.strftime(self.format_string)
return ''
def do_current_time(parser, token):
# This version uses a regular expression to parse tag contents.
try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
msg = '%r tag requires arguments' % token.contents[0]
raise template.TemplateSyntaxError(msg)
m = re.search(r'(.*?) as (\w+)', arg)
if m:
fmt, var_name = m.groups()
else:
msg = '%r tag had invalid arguments' % tag_name
raise template.TemplateSyntaxError(msg)
if not (fmt[0] == fmt[-1] and fmt[0] in ('"', "'")):
msg = "%r tag's argument should be in quotes" % tag_name
raise template.TemplateSyntaxError(msg)
return CurrentTimeNode3(fmt[1:-1], var_name)
[b]Parsing Until Another Template Tag[/b]
# in template:
# {% comment %}
def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()
class CommentNode(template.Node):
def render(self, context):
return ''
[b]Parsing Until Another Template Tag and Saving Contents[/b]
# in template:
# {% upper %}
This will appear in uppercase, {{ user_name }}.
# {% endupper %}
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()
[i]For more examples of complex rendering, see the source code for {% if %}, {% for %}, {% ifequal %}, and {% ifchanged %}. They live in django/template/defaulttags.py[/i]
[b]Shortcut for Simple Tags[/b]
def current_time(format_string):
try:
return datetime.datetime.now().strftime(str(format_string))
except UnicodeEncodeError:
return ''
register.simple_tag(current_time)
# python 2.4 above
@register.simple_tag
def current_time(token):
# ...
[b]Inclusion Tags[/b]
# inclusion tag using in template:
# {% books_for_author author %}
# template using by inclusion tag:
# <ul>
# {% for book in books %}
# <li>{{ book.title }}</li>
# {% endfor %}
# </ul>
def books_for_author(author):
books = Book.objects.filter(authors__id=author.id)
return {'books': books}
register.inclusion_tag('book_snippet.html')(books_for_author)
# python 2.4 above
@register.inclusion_tag('book_snippet.html')
def books_for_author(author):
# ...
[b]Inclusion tags access to values from the parent template’s context[/b]
@register.inclusion_tag('link.html', takes_context=True)
def jump_link(context):
return {
'link': context['home_link'],
'title': context['home_title'],
}
# in link.html
# Jump directly to <a href="{{ link }}">{{ title }}</a>.
# tag usage:
# {% jump_link %}
[b]Writing Custom Template Loaders[/b]
[code="Python"][/code]