Style and import fixes.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6641 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0e59bf42cf
commit
4e8864a882
|
@ -1,11 +1,12 @@
|
|||
"Default variable filters"
|
||||
"""Default variable filters."""
|
||||
|
||||
import re
|
||||
import random as random_module
|
||||
|
||||
from django.template import Variable, Library
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext, ungettext
|
||||
from django.utils.encoding import force_unicode, smart_str, iri_to_uri
|
||||
import re
|
||||
import random as random_module
|
||||
from django.utils.encoding import force_unicode, iri_to_uri
|
||||
|
||||
register = Library()
|
||||
|
||||
|
@ -36,17 +37,17 @@ def stringfilter(func):
|
|||
|
||||
|
||||
def addslashes(value):
|
||||
"Adds slashes - useful for passing strings to JavaScript, for example."
|
||||
"""Adds slashes - useful for passing strings to JavaScript, for example."""
|
||||
return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
|
||||
addslashes = stringfilter(addslashes)
|
||||
|
||||
def capfirst(value):
|
||||
"Capitalizes the first character of the value"
|
||||
"""Capitalizes the first character of the value."""
|
||||
return value and value[0].upper() + value[1:]
|
||||
capfirst = stringfilter(capfirst)
|
||||
|
||||
def fix_ampersands(value):
|
||||
"Replaces ampersands with ``&`` entities"
|
||||
"""Replaces ampersands with ``&`` entities."""
|
||||
from django.utils.html import fix_ampersands
|
||||
return fix_ampersands(value)
|
||||
fix_ampersands = stringfilter(fix_ampersands)
|
||||
|
@ -86,15 +87,16 @@ def floatformat(text, arg=-1):
|
|||
return formatstr % f
|
||||
|
||||
def iriencode(value):
|
||||
"Escapes an IRI value for use in a URL"
|
||||
"""Escapes an IRI value for use in a URL."""
|
||||
return force_unicode(iri_to_uri(value))
|
||||
iriencode = stringfilter(iriencode)
|
||||
|
||||
def linenumbers(value):
|
||||
"Displays text with line numbers"
|
||||
"""Displays text with line numbers."""
|
||||
from django.utils.html import escape
|
||||
lines = value.split(u'\n')
|
||||
# Find the maximum width of the line count, for use with zero padding string format command
|
||||
# Find the maximum width of the line count, for use with zero padding
|
||||
# string format command.
|
||||
width = unicode(len(unicode(len(lines))))
|
||||
for i, line in enumerate(lines):
|
||||
lines[i] = (u"%0" + width + u"d. %s") % (i + 1, escape(line))
|
||||
|
@ -102,22 +104,24 @@ def linenumbers(value):
|
|||
linenumbers = stringfilter(linenumbers)
|
||||
|
||||
def lower(value):
|
||||
"Converts a string into all lowercase"
|
||||
"""Converts a string into all lowercase."""
|
||||
return value.lower()
|
||||
lower = stringfilter(lower)
|
||||
|
||||
def make_list(value):
|
||||
"""
|
||||
Returns the value turned into a list. For an integer, it's a list of
|
||||
digits. For a string, it's a list of characters.
|
||||
Returns the value turned into a list.
|
||||
|
||||
For an integer, it's a list of digits.
|
||||
For a string, it's a list of characters.
|
||||
"""
|
||||
return list(value)
|
||||
make_list = stringfilter(make_list)
|
||||
|
||||
def slugify(value):
|
||||
"""
|
||||
Normalizes string, converts to lowercase, removes non-alpha chars and
|
||||
converts spaces to hyphens.
|
||||
Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||
and converts spaces to hyphens.
|
||||
"""
|
||||
import unicodedata
|
||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||
|
@ -127,7 +131,8 @@ slugify = stringfilter(slugify)
|
|||
|
||||
def stringformat(value, arg):
|
||||
"""
|
||||
Formats the variable according to the argument, a string formatting specifier.
|
||||
Formats the variable according to the arg, a string formatting specifier.
|
||||
|
||||
This specifier uses Python string formating syntax, with the exception that
|
||||
the leading "%" is dropped.
|
||||
|
||||
|
@ -140,29 +145,29 @@ def stringformat(value, arg):
|
|||
return u""
|
||||
|
||||
def title(value):
|
||||
"Converts a string into titlecase"
|
||||
"""Converts a string into titlecase."""
|
||||
return re.sub("([a-z])'([A-Z])", lambda m: m.group(0).lower(), value.title())
|
||||
title = stringfilter(title)
|
||||
|
||||
def truncatewords(value, arg):
|
||||
"""
|
||||
Truncates a string after a certain number of words
|
||||
Truncates a string after a certain number of words.
|
||||
|
||||
Argument: Number of words to truncate after
|
||||
Argument: Number of words to truncate after.
|
||||
"""
|
||||
from django.utils.text import truncate_words
|
||||
try:
|
||||
length = int(arg)
|
||||
except ValueError: # invalid literal for int()
|
||||
except ValueError: # Invalid literal for int().
|
||||
return value # Fail silently.
|
||||
return truncate_words(value, length)
|
||||
truncatewords = stringfilter(truncatewords)
|
||||
|
||||
def truncatewords_html(value, arg):
|
||||
"""
|
||||
Truncates HTML after a certain number of words
|
||||
Truncates HTML after a certain number of words.
|
||||
|
||||
Argument: Number of words to truncate after
|
||||
Argument: Number of words to truncate after.
|
||||
"""
|
||||
from django.utils.text import truncate_html_words
|
||||
try:
|
||||
|
@ -173,26 +178,26 @@ def truncatewords_html(value, arg):
|
|||
truncatewords_html = stringfilter(truncatewords_html)
|
||||
|
||||
def upper(value):
|
||||
"Converts a string into all uppercase"
|
||||
"""Converts a string into all uppercase."""
|
||||
return value.upper()
|
||||
upper = stringfilter(upper)
|
||||
|
||||
def urlencode(value):
|
||||
"Escapes a value for use in a URL"
|
||||
"""Escapes a value for use in a URL."""
|
||||
from django.utils.http import urlquote
|
||||
return urlquote(value)
|
||||
urlencode = stringfilter(urlencode)
|
||||
|
||||
def urlize(value):
|
||||
"Converts URLs in plain text into clickable links"
|
||||
"""Converts URLs in plain text into clickable links."""
|
||||
from django.utils.html import urlize
|
||||
return urlize(value, nofollow=True)
|
||||
urlize = stringfilter(urlize)
|
||||
|
||||
def urlizetrunc(value, limit):
|
||||
"""
|
||||
Converts URLs into clickable links, truncating URLs to the given character limit,
|
||||
and adding 'rel=nofollow' attribute to discourage spamming.
|
||||
Converts URLs into clickable links, truncating URLs to the given character
|
||||
limit, and adding 'rel=nofollow' attribute to discourage spamming.
|
||||
|
||||
Argument: Length to truncate URLs to.
|
||||
"""
|
||||
|
@ -201,13 +206,13 @@ def urlizetrunc(value, limit):
|
|||
urlizetrunc = stringfilter(urlizetrunc)
|
||||
|
||||
def wordcount(value):
|
||||
"Returns the number of words"
|
||||
"""Returns the number of words."""
|
||||
return len(value.split())
|
||||
wordcount = stringfilter(wordcount)
|
||||
|
||||
def wordwrap(value, arg):
|
||||
"""
|
||||
Wraps words at specified line length
|
||||
Wraps words at specified line length.
|
||||
|
||||
Argument: number of characters to wrap the text at.
|
||||
"""
|
||||
|
@ -217,29 +222,29 @@ wordwrap = stringfilter(wordwrap)
|
|||
|
||||
def ljust(value, arg):
|
||||
"""
|
||||
Left-aligns the value in a field of a given width
|
||||
Left-aligns the value in a field of a given width.
|
||||
|
||||
Argument: field size
|
||||
Argument: field size.
|
||||
"""
|
||||
return value.ljust(int(arg))
|
||||
ljust = stringfilter(ljust)
|
||||
|
||||
def rjust(value, arg):
|
||||
"""
|
||||
Right-aligns the value in a field of a given width
|
||||
Right-aligns the value in a field of a given width.
|
||||
|
||||
Argument: field size
|
||||
Argument: field size.
|
||||
"""
|
||||
return value.rjust(int(arg))
|
||||
rjust = stringfilter(rjust)
|
||||
|
||||
def center(value, arg):
|
||||
"Centers the value in a field of a given width"
|
||||
"""Centers the value in a field of a given width."""
|
||||
return value.center(int(arg))
|
||||
center = stringfilter(center)
|
||||
|
||||
def cut(value, arg):
|
||||
"Removes all values of arg from the given string"
|
||||
"""Removes all values of arg from the given string."""
|
||||
return value.replace(arg, u'')
|
||||
cut = stringfilter(cut)
|
||||
|
||||
|
@ -272,7 +277,7 @@ def linebreaksbr(value):
|
|||
linebreaksbr = stringfilter(linebreaksbr)
|
||||
|
||||
def removetags(value, tags):
|
||||
"Removes a space separated list of [X]HTML tags from the output"
|
||||
"""Removes a space separated list of [X]HTML tags from the output."""
|
||||
tags = [re.escape(tag) for tag in tags.split()]
|
||||
tags_re = u'(%s)' % u'|'.join(tags)
|
||||
starttag_re = re.compile(ur'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
|
||||
|
@ -283,7 +288,7 @@ def removetags(value, tags):
|
|||
removetags = stringfilter(removetags)
|
||||
|
||||
def striptags(value):
|
||||
"Strips all [X]HTML tags"
|
||||
"""Strips all [X]HTML tags."""
|
||||
from django.utils.html import strip_tags
|
||||
return strip_tags(value)
|
||||
striptags = stringfilter(striptags)
|
||||
|
@ -314,29 +319,29 @@ def dictsortreversed(value, arg):
|
|||
return [item[1] for item in decorated]
|
||||
|
||||
def first(value):
|
||||
"Returns the first item in a list"
|
||||
"""Returns the first item in a list."""
|
||||
try:
|
||||
return value[0]
|
||||
except IndexError:
|
||||
return u''
|
||||
|
||||
def join(value, arg):
|
||||
"Joins a list with a string, like Python's ``str.join(list)``"
|
||||
"""Joins a list with a string, like Python's ``str.join(list)``."""
|
||||
try:
|
||||
return arg.join(map(force_unicode, value))
|
||||
except AttributeError: # fail silently but nicely
|
||||
return value
|
||||
|
||||
def length(value):
|
||||
"Returns the length of the value - useful for lists"
|
||||
"""Returns the length of the value - useful for lists."""
|
||||
return len(value)
|
||||
|
||||
def length_is(value, arg):
|
||||
"Returns a boolean of whether the value's length is the argument"
|
||||
"""Returns a boolean of whether the value's length is the argument."""
|
||||
return len(value) == int(arg)
|
||||
|
||||
def random(value):
|
||||
"Returns a random item from the list"
|
||||
"""Returns a random item from the list."""
|
||||
return random_module.choice(value)
|
||||
|
||||
def slice_(value, arg):
|
||||
|
@ -416,7 +421,7 @@ def unordered_list(value):
|
|||
sublist = ''
|
||||
sublist_item = None
|
||||
if isinstance(title, (list, tuple)):
|
||||
sublist_item = title
|
||||
sublist_item = title
|
||||
title = ''
|
||||
elif i < list_length - 1:
|
||||
next_item = list_[i+1]
|
||||
|
@ -424,7 +429,7 @@ def unordered_list(value):
|
|||
# The next item is a sub-list.
|
||||
sublist_item = next_item
|
||||
# We've processed the next item now too.
|
||||
i += 1
|
||||
i += 1
|
||||
if sublist_item:
|
||||
sublist = _helper(sublist_item, tabs+1)
|
||||
sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist,
|
||||
|
@ -433,7 +438,7 @@ def unordered_list(value):
|
|||
sublist))
|
||||
i += 1
|
||||
return '\n'.join(output)
|
||||
value, converted = convert_old_style_list(value)
|
||||
value, converted = convert_old_style_list(value)
|
||||
return _helper(value)
|
||||
|
||||
###################
|
||||
|
@ -441,7 +446,7 @@ def unordered_list(value):
|
|||
###################
|
||||
|
||||
def add(value, arg):
|
||||
"Adds the arg to the value"
|
||||
"""Adds the arg to the value."""
|
||||
return int(value) + int(arg)
|
||||
|
||||
def get_digit(value, arg):
|
||||
|
@ -468,7 +473,7 @@ def get_digit(value, arg):
|
|||
###################
|
||||
|
||||
def date(value, arg=None):
|
||||
"Formats a date according to the given format"
|
||||
"""Formats a date according to the given format."""
|
||||
from django.utils.dateformat import format
|
||||
if not value:
|
||||
return u''
|
||||
|
@ -477,7 +482,7 @@ def date(value, arg=None):
|
|||
return format(value, arg)
|
||||
|
||||
def time(value, arg=None):
|
||||
"Formats a time according to the given format"
|
||||
"""Formats a time according to the given format."""
|
||||
from django.utils.dateformat import time_format
|
||||
if value in (None, u''):
|
||||
return u''
|
||||
|
@ -486,7 +491,7 @@ def time(value, arg=None):
|
|||
return time_format(value, arg)
|
||||
|
||||
def timesince(value, arg=None):
|
||||
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
|
||||
"""Formats a date as the time since that date (i.e. "4 days, 6 hours")."""
|
||||
from django.utils.timesince import timesince
|
||||
if not value:
|
||||
return u''
|
||||
|
@ -495,7 +500,7 @@ def timesince(value, arg=None):
|
|||
return timesince(value)
|
||||
|
||||
def timeuntil(value, arg=None):
|
||||
'Formats a date as the time until that date (i.e. "4 days, 6 hours")'
|
||||
"""Formats a date as the time until that date (i.e. "4 days, 6 hours")."""
|
||||
from django.utils.timesince import timesince
|
||||
from datetime import datetime
|
||||
if not value:
|
||||
|
@ -509,17 +514,17 @@ def timeuntil(value, arg=None):
|
|||
###################
|
||||
|
||||
def default(value, arg):
|
||||
"If value is unavailable, use given default"
|
||||
"""If value is unavailable, use given default."""
|
||||
return value or arg
|
||||
|
||||
def default_if_none(value, arg):
|
||||
"If value is None, use given default"
|
||||
"""If value is None, use given default."""
|
||||
if value is None:
|
||||
return arg
|
||||
return value
|
||||
|
||||
def divisibleby(value, arg):
|
||||
"Returns true if the value is devisible by the argument"
|
||||
"""Returns True if the value is devisible by the argument."""
|
||||
return int(value) % int(arg) == 0
|
||||
|
||||
def yesno(value, arg=None):
|
||||
|
@ -544,7 +549,8 @@ def yesno(value, arg=None):
|
|||
return value # Invalid arg.
|
||||
try:
|
||||
yes, no, maybe = bits
|
||||
except ValueError: # unpack list of wrong size (no "maybe" value provided)
|
||||
except ValueError:
|
||||
# Unpack list of wrong size (no "maybe" value provided).
|
||||
yes, no, maybe = bits[0], bits[1], bits[1]
|
||||
if value is None:
|
||||
return maybe
|
||||
|
@ -558,8 +564,8 @@ def yesno(value, arg=None):
|
|||
|
||||
def filesizeformat(bytes):
|
||||
"""
|
||||
Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
|
||||
bytes, etc).
|
||||
Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB,
|
||||
102 bytes, etc).
|
||||
"""
|
||||
try:
|
||||
bytes = float(bytes)
|
||||
|
@ -591,23 +597,23 @@ def pluralize(value, arg=u's'):
|
|||
try:
|
||||
if int(value) != 1:
|
||||
return plural_suffix
|
||||
except ValueError: # invalid string that's not a number
|
||||
except ValueError: # Invalid string that's not a number.
|
||||
pass
|
||||
except TypeError: # value isn't a string or a number; maybe it's a list?
|
||||
except TypeError: # Value isn't a string or a number; maybe it's a list?
|
||||
try:
|
||||
if len(value) != 1:
|
||||
return plural_suffix
|
||||
except TypeError: # len() of unsized object
|
||||
except TypeError: # len() of unsized object.
|
||||
pass
|
||||
return singular_suffix
|
||||
|
||||
def phone2numeric(value):
|
||||
"Takes a phone number and converts it in to its numerical equivalent"
|
||||
"""Takes a phone number and converts it in to its numerical equivalent."""
|
||||
from django.utils.text import phone2numeric
|
||||
return phone2numeric(value)
|
||||
|
||||
def pprint(value):
|
||||
"A wrapper around pprint.pprint -- for debugging, really"
|
||||
"""A wrapper around pprint.pprint -- for debugging, really."""
|
||||
from pprint import pformat
|
||||
try:
|
||||
return pformat(value)
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
"Default tags used by the template system, available to all templates."
|
||||
"""Default tags used by the template system, available to all templates."""
|
||||
|
||||
import sys
|
||||
import re
|
||||
from itertools import cycle as itertools_cycle
|
||||
try:
|
||||
reversed
|
||||
except NameError:
|
||||
from django.utils.itercompat import reversed # Python 2.3 fallback
|
||||
|
||||
from django.template import Node, NodeList, Template, Context, Variable
|
||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
|
||||
|
@ -8,13 +14,6 @@ from django.template import get_library, Library, InvalidTemplateLibrary
|
|||
from django.conf import settings
|
||||
from django.utils.encoding import smart_str, smart_unicode
|
||||
from django.utils.itercompat import groupby
|
||||
import sys
|
||||
import re
|
||||
|
||||
try:
|
||||
reversed
|
||||
except NameError:
|
||||
from django.utils.itercompat import reversed # Python 2.3 fallback
|
||||
|
||||
register = Library()
|
||||
|
||||
|
@ -48,7 +47,7 @@ class FilterNode(Node):
|
|||
|
||||
def render(self, context):
|
||||
output = self.nodelist.render(context)
|
||||
# apply filters
|
||||
# Apply filters.
|
||||
context.update({'var': output})
|
||||
filtered = self.filter_expr.resolve(context)
|
||||
context.pop()
|
||||
|
@ -80,7 +79,8 @@ class ForNode(Node):
|
|||
else:
|
||||
reversed = ''
|
||||
return "<For Node: for %s in %s, tail_len: %d%s>" % \
|
||||
(', '.join( self.loopvars ), self.sequence, len(self.nodelist_loop), reversed)
|
||||
(', '.join(self.loopvars), self.sequence, len(self.nodelist_loop),
|
||||
reversed)
|
||||
|
||||
def __iter__(self):
|
||||
for node in self.nodelist_loop:
|
||||
|
@ -114,19 +114,20 @@ class ForNode(Node):
|
|||
unpack = len(self.loopvars) > 1
|
||||
for i, item in enumerate(values):
|
||||
context['forloop'] = {
|
||||
# shortcuts for current loop iteration number
|
||||
# Shortcuts for current loop iteration number.
|
||||
'counter0': i,
|
||||
'counter': i+1,
|
||||
# reverse counter iteration numbers
|
||||
# Reverse counter iteration numbers.
|
||||
'revcounter': len_values - i,
|
||||
'revcounter0': len_values - i - 1,
|
||||
# boolean values designating first and last times through loop
|
||||
# Boolean values designating first and last times through loop.
|
||||
'first': (i == 0),
|
||||
'last': (i == len_values - 1),
|
||||
'parentloop': parentloop,
|
||||
}
|
||||
if unpack:
|
||||
# If there are multiple loop variables, unpack the item into them.
|
||||
# If there are multiple loop variables, unpack the item into
|
||||
# them.
|
||||
context.update(dict(zip(self.loopvars, item)))
|
||||
else:
|
||||
context[self.loopvars[0]] = item
|
||||
|
@ -153,8 +154,8 @@ class IfChangedNode(Node):
|
|||
self._last_seen = None
|
||||
try:
|
||||
if self._varlist:
|
||||
# Consider multiple parameters.
|
||||
# This automatically behaves like a OR evaluation of the multiple variables.
|
||||
# Consider multiple parameters. This automatically behaves
|
||||
# like an OR evaluation of the multiple variables.
|
||||
compare_to = [var.resolve(context) for var in self._varlist]
|
||||
else:
|
||||
compare_to = self.nodelist.render(context)
|
||||
|
@ -248,13 +249,17 @@ class RegroupNode(Node):
|
|||
|
||||
def render(self, context):
|
||||
obj_list = self.target.resolve(context, True)
|
||||
if obj_list == None: # target_var wasn't found in context; fail silently
|
||||
if obj_list == None:
|
||||
# target variable wasn't found in context; fail silently.
|
||||
context[self.var_name] = []
|
||||
return ''
|
||||
# List of dictionaries in the format
|
||||
# List of dictionaries in the format:
|
||||
# {'grouper': 'key', 'list': [list of contents]}.
|
||||
context[self.var_name] = [{'grouper':key, 'list':list(val)} for key, val in
|
||||
groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))]
|
||||
context[self.var_name] = [
|
||||
{'grouper': key, 'list': list(val)}
|
||||
for key, val in
|
||||
groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))
|
||||
]
|
||||
return ''
|
||||
|
||||
def include_is_allowed(filepath):
|
||||
|
@ -338,13 +343,15 @@ class URLNode(Node):
|
|||
def render(self, context):
|
||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||
args = [arg.resolve(context) for arg in self.args]
|
||||
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context)) for k, v in self.kwargs.items()])
|
||||
kwargs = dict([(smart_str(k,'ascii'), v.resolve(context))
|
||||
for k, v in self.kwargs.items()])
|
||||
try:
|
||||
return reverse(self.view_name, args=args, kwargs=kwargs)
|
||||
except NoReverseMatch:
|
||||
try:
|
||||
project_name = settings.SETTINGS_MODULE.split('.')[0]
|
||||
return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs)
|
||||
return reverse(project_name + '.' + self.view_name,
|
||||
args=args, kwargs=kwargs)
|
||||
except NoReverseMatch:
|
||||
return ''
|
||||
|
||||
|
@ -388,7 +395,7 @@ class WithNode(Node):
|
|||
#@register.tag
|
||||
def comment(parser, token):
|
||||
"""
|
||||
Ignore everything between ``{% comment %}`` and ``{% endcomment %}``
|
||||
Ignores everything between ``{% comment %}`` and ``{% endcomment %}``.
|
||||
"""
|
||||
parser.skip_past('endcomment')
|
||||
return CommentNode()
|
||||
|
@ -397,7 +404,7 @@ comment = register.tag(comment)
|
|||
#@register.tag
|
||||
def cycle(parser, token):
|
||||
"""
|
||||
Cycle among the given strings each time this tag is encountered
|
||||
Cycles among the given strings each time this tag is encountered.
|
||||
|
||||
Within a loop, cycles among the given strings each time through
|
||||
the loop::
|
||||
|
@ -416,14 +423,14 @@ def cycle(parser, token):
|
|||
<tr class="{% cycle rowcolors %}">...</tr>
|
||||
|
||||
You can use any number of values, seperated by spaces. Commas can also
|
||||
be used to separate values; if a comma is used, the cycle values are
|
||||
be used to separate values; if a comma is used, the cycle values are
|
||||
interpreted as literal strings.
|
||||
"""
|
||||
|
||||
# Note: This returns the exact same node on each {% cycle name %} call; that
|
||||
# is, the node object returned from {% cycle a b c as name %} and the one
|
||||
# returned from {% cycle name %} are the exact same object. This shouldn't
|
||||
# cause problems (heh), but if it does, now you know.
|
||||
# Note: This returns the exact same node on each {% cycle name %} call;
|
||||
# that is, the node object returned from {% cycle a b c as name %} and the
|
||||
# one returned from {% cycle name %} are the exact same object. This
|
||||
# shouldn't cause problems (heh), but if it does, now you know.
|
||||
#
|
||||
# Ugly hack warning: this stuffs the named template dict into parser so
|
||||
# that names are only unique within each template (as opposed to using
|
||||
|
@ -441,10 +448,11 @@ def cycle(parser, token):
|
|||
args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
|
||||
|
||||
if len(args) == 2:
|
||||
# {% cycle foo %} case
|
||||
# {% cycle foo %} case.
|
||||
name = args[1]
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name)
|
||||
raise TemplateSyntaxError("No named cycles in template."
|
||||
" '%s' is not defined" % name)
|
||||
if not name in parser._namedCycleNodes:
|
||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||
return parser._namedCycleNodes[name]
|
||||
|
@ -462,7 +470,8 @@ cycle = register.tag(cycle)
|
|||
|
||||
def debug(parser, token):
|
||||
"""
|
||||
Output a whole load of debugging information, including the current context and imported modules.
|
||||
Outputs a whole load of debugging information, including the current
|
||||
context and imported modules.
|
||||
|
||||
Sample usage::
|
||||
|
||||
|
@ -476,7 +485,7 @@ debug = register.tag(debug)
|
|||
#@register.tag(name="filter")
|
||||
def do_filter(parser, token):
|
||||
"""
|
||||
Filter the contents of the blog through variable filters.
|
||||
Filters the contents of the blog through variable filters.
|
||||
|
||||
Filters can also be piped through each other, and they can have
|
||||
arguments -- just like in variable syntax.
|
||||
|
@ -525,14 +534,15 @@ def firstof(parser, token):
|
|||
"""
|
||||
bits = token.split_contents()[1:]
|
||||
if len(bits) < 1:
|
||||
raise TemplateSyntaxError, "'firstof' statement requires at least one argument"
|
||||
raise TemplateSyntaxError("'firstof' statement requires at least one"
|
||||
" argument")
|
||||
return FirstOfNode(bits)
|
||||
firstof = register.tag(firstof)
|
||||
|
||||
#@register.tag(name="for")
|
||||
def do_for(parser, token):
|
||||
"""
|
||||
Loop over each item in an array.
|
||||
Loops over each item in an array.
|
||||
|
||||
For example, to display a list of athletes given ``athlete_list``::
|
||||
|
||||
|
@ -544,9 +554,9 @@ def do_for(parser, token):
|
|||
|
||||
You can loop over a list in reverse by using
|
||||
``{% for obj in list reversed %}``.
|
||||
|
||||
|
||||
You can also unpack multiple values from a two-dimensional array::
|
||||
|
||||
|
||||
{% for key,value in dict.items %}
|
||||
{{ key }}: {{ value }}
|
||||
{% endfor %}
|
||||
|
@ -571,17 +581,20 @@ def do_for(parser, token):
|
|||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) < 4:
|
||||
raise TemplateSyntaxError, "'for' statements should have at least four words: %s" % token.contents
|
||||
raise TemplateSyntaxError("'for' statements should have at least four"
|
||||
" words: %s" % token.contents)
|
||||
|
||||
reversed = bits[-1] == 'reversed'
|
||||
in_index = reversed and -3 or -2
|
||||
if bits[in_index] != 'in':
|
||||
raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents
|
||||
raise TemplateSyntaxError("'for' statements should use the format"
|
||||
" 'for x in y': %s" % token.contents)
|
||||
|
||||
loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',')
|
||||
for var in loopvars:
|
||||
if not var or ' ' in var:
|
||||
raise TemplateSyntaxError, "'for' tag received an invalid argument: %s" % token.contents
|
||||
raise TemplateSyntaxError("'for' tag received an invalid argument:"
|
||||
" %s" % token.contents)
|
||||
|
||||
sequence = parser.compile_filter(bits[in_index+1])
|
||||
nodelist_loop = parser.parse(('endfor',))
|
||||
|
@ -606,7 +619,7 @@ def do_ifequal(parser, token, negate):
|
|||
#@register.tag
|
||||
def ifequal(parser, token):
|
||||
"""
|
||||
Output the contents of the block if the two arguments equal each other.
|
||||
Outputs the contents of the block if the two arguments equal each other.
|
||||
|
||||
Examples::
|
||||
|
||||
|
@ -625,7 +638,10 @@ ifequal = register.tag(ifequal)
|
|||
|
||||
#@register.tag
|
||||
def ifnotequal(parser, token):
|
||||
"""Output the contents of the block if the two arguments are not equal. See ifequal."""
|
||||
"""
|
||||
Outputs the contents of the block if the two arguments are not equal.
|
||||
See ifequal.
|
||||
"""
|
||||
return do_ifequal(parser, token, True)
|
||||
ifnotequal = register.tag(ifnotequal)
|
||||
|
||||
|
@ -634,9 +650,7 @@ def do_if(parser, token):
|
|||
"""
|
||||
The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
|
||||
(i.e. exists, is not empty, and is not a false boolean value) the contents
|
||||
of the block are output:
|
||||
|
||||
::
|
||||
of the block are output::
|
||||
|
||||
{% if athlete_list %}
|
||||
Number of athletes: {{ athlete_list|count }}
|
||||
|
@ -647,8 +661,8 @@ def do_if(parser, token):
|
|||
In the above, if ``athlete_list`` is not empty, the number of athletes will
|
||||
be displayed by the ``{{ athlete_list|count }}`` variable.
|
||||
|
||||
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
||||
will be displayed if the test fails.
|
||||
As you can see, the ``if`` tag can take an option ``{% else %}`` clause
|
||||
that will be displayed if the test fails.
|
||||
|
||||
``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
|
||||
variables or to negate a given variable::
|
||||
|
@ -673,9 +687,9 @@ def do_if(parser, token):
|
|||
There are some athletes and absolutely no coaches.
|
||||
{% endif %}
|
||||
|
||||
``if`` tags do not allow ``and`` and ``or`` clauses with the same
|
||||
tag, because the order of logic would be ambigous. For example,
|
||||
this is invalid::
|
||||
``if`` tags do not allow ``and`` and ``or`` clauses with the same tag,
|
||||
because the order of logic would be ambigous. For example, this is
|
||||
invalid::
|
||||
|
||||
{% if athlete_list and coach_list or cheerleader_list %}
|
||||
|
||||
|
@ -691,8 +705,8 @@ def do_if(parser, token):
|
|||
bits = token.contents.split()
|
||||
del bits[0]
|
||||
if not bits:
|
||||
raise TemplateSyntaxError, "'if' statement requires at least one argument"
|
||||
# bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
||||
raise TemplateSyntaxError("'if' statement requires at least one argument")
|
||||
# Bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
||||
bitstr = ' '.join(bits)
|
||||
boolpairs = bitstr.split(' and ')
|
||||
boolvars = []
|
||||
|
@ -727,13 +741,13 @@ do_if = register.tag("if", do_if)
|
|||
#@register.tag
|
||||
def ifchanged(parser, token):
|
||||
"""
|
||||
Check if a value has changed from the last iteration of a loop.
|
||||
Checks if a value has changed from the last iteration of a loop.
|
||||
|
||||
The 'ifchanged' block tag is used within a loop. It has two possible uses.
|
||||
|
||||
1. Checks its own rendered contents against its previous state and only
|
||||
displays the content if it has changed. For example, this displays a list of
|
||||
days, only displaying the month if it changes::
|
||||
displays the content if it has changed. For example, this displays a
|
||||
list of days, only displaying the month if it changes::
|
||||
|
||||
<h1>Archive for {{ year }}</h1>
|
||||
|
||||
|
@ -742,9 +756,9 @@ def ifchanged(parser, token):
|
|||
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
||||
{% endfor %}
|
||||
|
||||
2. If given a variable, check whether that variable has changed. For example, the
|
||||
following shows the date every time it changes, but only shows the hour if both
|
||||
the hour and the date have changed::
|
||||
2. If given a variable, check whether that variable has changed.
|
||||
For example, the following shows the date every time it changes, but
|
||||
only shows the hour if both the hour and the date have changed::
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
|
||||
|
@ -762,7 +776,7 @@ ifchanged = register.tag(ifchanged)
|
|||
#@register.tag
|
||||
def ssi(parser, token):
|
||||
"""
|
||||
Output the contents of a given file into the page.
|
||||
Outputs the contents of a given file into the page.
|
||||
|
||||
Like a simple "include" tag, the ``ssi`` tag includes the contents
|
||||
of another file -- which must be specified using an absolute page --
|
||||
|
@ -778,21 +792,24 @@ def ssi(parser, token):
|
|||
bits = token.contents.split()
|
||||
parsed = False
|
||||
if len(bits) not in (2, 3):
|
||||
raise TemplateSyntaxError, "'ssi' tag takes one argument: the path to the file to be included"
|
||||
raise TemplateSyntaxError("'ssi' tag takes one argument: the path to"
|
||||
" the file to be included")
|
||||
if len(bits) == 3:
|
||||
if bits[2] == 'parsed':
|
||||
parsed = True
|
||||
else:
|
||||
raise TemplateSyntaxError, "Second (optional) argument to %s tag must be 'parsed'" % bits[0]
|
||||
raise TemplateSyntaxError("Second (optional) argument to %s tag"
|
||||
" must be 'parsed'" % bits[0])
|
||||
return SsiNode(bits[1], parsed)
|
||||
ssi = register.tag(ssi)
|
||||
|
||||
#@register.tag
|
||||
def load(parser, token):
|
||||
"""
|
||||
Load a custom template tag set.
|
||||
Loads a custom template tag set.
|
||||
|
||||
For example, to load the template tags in ``django/templatetags/news/photos.py``::
|
||||
For example, to load the template tags in
|
||||
``django/templatetags/news/photos.py``::
|
||||
|
||||
{% load news.photos %}
|
||||
"""
|
||||
|
@ -803,14 +820,15 @@ def load(parser, token):
|
|||
lib = get_library("django.templatetags.%s" % taglib)
|
||||
parser.add_library(lib)
|
||||
except InvalidTemplateLibrary, e:
|
||||
raise TemplateSyntaxError, "'%s' is not a valid tag library: %s" % (taglib, e)
|
||||
raise TemplateSyntaxError("'%s' is not a valid tag library: %s" %
|
||||
(taglib, e))
|
||||
return LoadNode()
|
||||
load = register.tag(load)
|
||||
|
||||
#@register.tag
|
||||
def now(parser, token):
|
||||
"""
|
||||
Display the date, formatted according to the given string.
|
||||
Displays the date, formatted according to the given string.
|
||||
|
||||
Uses the same format as PHP's ``date()`` function; see http://php.net/date
|
||||
for all the possible values.
|
||||
|
@ -829,7 +847,7 @@ now = register.tag(now)
|
|||
#@register.tag
|
||||
def regroup(parser, token):
|
||||
"""
|
||||
Regroup a list of alike objects by a common attribute.
|
||||
Regroups a list of alike objects by a common attribute.
|
||||
|
||||
This complex tag is best illustrated by use of an example: say that
|
||||
``people`` is a list of ``Person`` objects that have ``first_name``,
|
||||
|
@ -867,8 +885,8 @@ def regroup(parser, token):
|
|||
|
||||
Note that `{% regroup %}`` does not work when the list to be grouped is not
|
||||
sorted by the key you are grouping by! This means that if your list of
|
||||
people was not sorted by gender, you'd need to make sure it is sorted before
|
||||
using it, i.e.::
|
||||
people was not sorted by gender, you'd need to make sure it is sorted
|
||||
before using it, i.e.::
|
||||
|
||||
{% regroup people|dictsort:"gender" by gender as grouped %}
|
||||
|
||||
|
@ -878,10 +896,11 @@ def regroup(parser, token):
|
|||
raise TemplateSyntaxError, "'regroup' tag takes five arguments"
|
||||
target = parser.compile_filter(firstbits[1])
|
||||
if firstbits[2] != 'by':
|
||||
raise TemplateSyntaxError, "second argument to 'regroup' tag must be 'by'"
|
||||
raise TemplateSyntaxError("second argument to 'regroup' tag must be 'by'")
|
||||
lastbits_reversed = firstbits[3][::-1].split(None, 2)
|
||||
if lastbits_reversed[1][::-1] != 'as':
|
||||
raise TemplateSyntaxError, "next-to-last argument to 'regroup' tag must be 'as'"
|
||||
raise TemplateSyntaxError("next-to-last argument to 'regroup' tag must"
|
||||
" be 'as'")
|
||||
|
||||
expression = parser.compile_filter(lastbits_reversed[2][::-1])
|
||||
|
||||
|
@ -891,8 +910,7 @@ regroup = register.tag(regroup)
|
|||
|
||||
def spaceless(parser, token):
|
||||
"""
|
||||
Removes whitespace between HTML tags. This includes tab
|
||||
characters and newlines.
|
||||
Removes whitespace between HTML tags, including tab and newline characters.
|
||||
|
||||
Example usage::
|
||||
|
||||
|
@ -906,8 +924,8 @@ def spaceless(parser, token):
|
|||
|
||||
<p><a href="foo/">Foo</a></p>
|
||||
|
||||
Only space between *tags* is normalized -- not space between tags and text. In
|
||||
this example, the space around ``Hello`` won't be stripped::
|
||||
Only space between *tags* is normalized -- not space between tags and text.
|
||||
In this example, the space around ``Hello`` won't be stripped::
|
||||
|
||||
{% spaceless %}
|
||||
<strong>
|
||||
|
@ -923,7 +941,7 @@ spaceless = register.tag(spaceless)
|
|||
#@register.tag
|
||||
def templatetag(parser, token):
|
||||
"""
|
||||
Output one of the bits used to compose template tags.
|
||||
Outputs one of the bits used to compose template tags.
|
||||
|
||||
Since the template system has no concept of "escaping", to display one of
|
||||
the bits used in template tags, you must use the ``{% templatetag %}`` tag.
|
||||
|
@ -948,8 +966,9 @@ def templatetag(parser, token):
|
|||
raise TemplateSyntaxError, "'templatetag' statement takes one argument"
|
||||
tag = bits[1]
|
||||
if tag not in TemplateTagNode.mapping:
|
||||
raise TemplateSyntaxError, "Invalid templatetag argument: '%s'. Must be one of: %s" % \
|
||||
(tag, TemplateTagNode.mapping.keys())
|
||||
raise TemplateSyntaxError("Invalid templatetag argument: '%s'."
|
||||
" Must be one of: %s" %
|
||||
(tag, TemplateTagNode.mapping.keys()))
|
||||
return TemplateTagNode(tag)
|
||||
templatetag = register.tag(templatetag)
|
||||
|
||||
|
@ -957,7 +976,8 @@ def url(parser, token):
|
|||
"""
|
||||
Returns an absolute URL matching given view with its parameters.
|
||||
|
||||
This is a way to define links that aren't tied to a particular URL configuration::
|
||||
This is a way to define links that aren't tied to a particular URL
|
||||
configuration::
|
||||
|
||||
{% url path.to.some_view arg1,arg2,name1=value1 %}
|
||||
|
||||
|
@ -985,7 +1005,8 @@ def url(parser, token):
|
|||
"""
|
||||
bits = token.contents.split(' ', 2)
|
||||
if len(bits) < 2:
|
||||
raise TemplateSyntaxError, "'%s' takes at least one argument (path to a view)" % bits[0]
|
||||
raise TemplateSyntaxError("'%s' takes at least one argument"
|
||||
" (path to a view)" % bits[0])
|
||||
args = []
|
||||
kwargs = {}
|
||||
if len(bits) > 2:
|
||||
|
@ -1010,8 +1031,8 @@ def widthratio(parser, token):
|
|||
<img src='bar.gif' height='10' width='{% widthratio this_value max_value 100 %}' />
|
||||
|
||||
Above, if ``this_value`` is 175 and ``max_value`` is 200, the the image in
|
||||
the above example will be 88 pixels wide (because 175/200 = .875; .875 *
|
||||
100 = 87.5 which is rounded up to 88).
|
||||
the above example will be 88 pixels wide (because 175/200 = .875;
|
||||
.875 * 100 = 87.5 which is rounded up to 88).
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 4:
|
||||
|
@ -1028,7 +1049,7 @@ widthratio = register.tag(widthratio)
|
|||
#@register.tag
|
||||
def do_with(parser, token):
|
||||
"""
|
||||
Add a value to the context (inside of this block) for caching and easy
|
||||
Adds a value to the context (inside of this block) for caching and easy
|
||||
access.
|
||||
|
||||
For example::
|
||||
|
@ -1039,7 +1060,8 @@ def do_with(parser, token):
|
|||
"""
|
||||
bits = list(token.split_contents())
|
||||
if len(bits) != 4 or bits[2] != "as":
|
||||
raise TemplateSyntaxError, "%r expected format is 'value as name'" % bits[0]
|
||||
raise TemplateSyntaxError("%r expected format is 'value as name'" %
|
||||
bits[0])
|
||||
var = parser.compile_filter(bits[1])
|
||||
name = bits[3]
|
||||
nodelist = parser.parse(('endwith',))
|
||||
|
|
Loading…
Reference in New Issue