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.template import Variable, Library
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext, ungettext
|
from django.utils.translation import ugettext, ungettext
|
||||||
from django.utils.encoding import force_unicode, smart_str, iri_to_uri
|
from django.utils.encoding import force_unicode, iri_to_uri
|
||||||
import re
|
|
||||||
import random as random_module
|
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
|
@ -36,17 +37,17 @@ def stringfilter(func):
|
||||||
|
|
||||||
|
|
||||||
def addslashes(value):
|
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("'", "\\'")
|
return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'")
|
||||||
addslashes = stringfilter(addslashes)
|
addslashes = stringfilter(addslashes)
|
||||||
|
|
||||||
def capfirst(value):
|
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:]
|
return value and value[0].upper() + value[1:]
|
||||||
capfirst = stringfilter(capfirst)
|
capfirst = stringfilter(capfirst)
|
||||||
|
|
||||||
def fix_ampersands(value):
|
def fix_ampersands(value):
|
||||||
"Replaces ampersands with ``&`` entities"
|
"""Replaces ampersands with ``&`` entities."""
|
||||||
from django.utils.html import fix_ampersands
|
from django.utils.html import fix_ampersands
|
||||||
return fix_ampersands(value)
|
return fix_ampersands(value)
|
||||||
fix_ampersands = stringfilter(fix_ampersands)
|
fix_ampersands = stringfilter(fix_ampersands)
|
||||||
|
@ -86,15 +87,16 @@ def floatformat(text, arg=-1):
|
||||||
return formatstr % f
|
return formatstr % f
|
||||||
|
|
||||||
def iriencode(value):
|
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))
|
return force_unicode(iri_to_uri(value))
|
||||||
iriencode = stringfilter(iriencode)
|
iriencode = stringfilter(iriencode)
|
||||||
|
|
||||||
def linenumbers(value):
|
def linenumbers(value):
|
||||||
"Displays text with line numbers"
|
"""Displays text with line numbers."""
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
lines = value.split(u'\n')
|
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))))
|
width = unicode(len(unicode(len(lines))))
|
||||||
for i, line in enumerate(lines):
|
for i, line in enumerate(lines):
|
||||||
lines[i] = (u"%0" + width + u"d. %s") % (i + 1, escape(line))
|
lines[i] = (u"%0" + width + u"d. %s") % (i + 1, escape(line))
|
||||||
|
@ -102,22 +104,24 @@ def linenumbers(value):
|
||||||
linenumbers = stringfilter(linenumbers)
|
linenumbers = stringfilter(linenumbers)
|
||||||
|
|
||||||
def lower(value):
|
def lower(value):
|
||||||
"Converts a string into all lowercase"
|
"""Converts a string into all lowercase."""
|
||||||
return value.lower()
|
return value.lower()
|
||||||
lower = stringfilter(lower)
|
lower = stringfilter(lower)
|
||||||
|
|
||||||
def make_list(value):
|
def make_list(value):
|
||||||
"""
|
"""
|
||||||
Returns the value turned into a list. For an integer, it's a list of
|
Returns the value turned into a list.
|
||||||
digits. For a string, it's a list of characters.
|
|
||||||
|
For an integer, it's a list of digits.
|
||||||
|
For a string, it's a list of characters.
|
||||||
"""
|
"""
|
||||||
return list(value)
|
return list(value)
|
||||||
make_list = stringfilter(make_list)
|
make_list = stringfilter(make_list)
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
"""
|
"""
|
||||||
Normalizes string, converts to lowercase, removes non-alpha chars and
|
Normalizes string, converts to lowercase, removes non-alpha characters,
|
||||||
converts spaces to hyphens.
|
and converts spaces to hyphens.
|
||||||
"""
|
"""
|
||||||
import unicodedata
|
import unicodedata
|
||||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||||
|
@ -127,7 +131,8 @@ slugify = stringfilter(slugify)
|
||||||
|
|
||||||
def stringformat(value, arg):
|
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
|
This specifier uses Python string formating syntax, with the exception that
|
||||||
the leading "%" is dropped.
|
the leading "%" is dropped.
|
||||||
|
|
||||||
|
@ -140,29 +145,29 @@ def stringformat(value, arg):
|
||||||
return u""
|
return u""
|
||||||
|
|
||||||
def title(value):
|
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())
|
return re.sub("([a-z])'([A-Z])", lambda m: m.group(0).lower(), value.title())
|
||||||
title = stringfilter(title)
|
title = stringfilter(title)
|
||||||
|
|
||||||
def truncatewords(value, arg):
|
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
|
from django.utils.text import truncate_words
|
||||||
try:
|
try:
|
||||||
length = int(arg)
|
length = int(arg)
|
||||||
except ValueError: # invalid literal for int()
|
except ValueError: # Invalid literal for int().
|
||||||
return value # Fail silently.
|
return value # Fail silently.
|
||||||
return truncate_words(value, length)
|
return truncate_words(value, length)
|
||||||
truncatewords = stringfilter(truncatewords)
|
truncatewords = stringfilter(truncatewords)
|
||||||
|
|
||||||
def truncatewords_html(value, arg):
|
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
|
from django.utils.text import truncate_html_words
|
||||||
try:
|
try:
|
||||||
|
@ -173,26 +178,26 @@ def truncatewords_html(value, arg):
|
||||||
truncatewords_html = stringfilter(truncatewords_html)
|
truncatewords_html = stringfilter(truncatewords_html)
|
||||||
|
|
||||||
def upper(value):
|
def upper(value):
|
||||||
"Converts a string into all uppercase"
|
"""Converts a string into all uppercase."""
|
||||||
return value.upper()
|
return value.upper()
|
||||||
upper = stringfilter(upper)
|
upper = stringfilter(upper)
|
||||||
|
|
||||||
def urlencode(value):
|
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
|
from django.utils.http import urlquote
|
||||||
return urlquote(value)
|
return urlquote(value)
|
||||||
urlencode = stringfilter(urlencode)
|
urlencode = stringfilter(urlencode)
|
||||||
|
|
||||||
def urlize(value):
|
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
|
from django.utils.html import urlize
|
||||||
return urlize(value, nofollow=True)
|
return urlize(value, nofollow=True)
|
||||||
urlize = stringfilter(urlize)
|
urlize = stringfilter(urlize)
|
||||||
|
|
||||||
def urlizetrunc(value, limit):
|
def urlizetrunc(value, limit):
|
||||||
"""
|
"""
|
||||||
Converts URLs into clickable links, truncating URLs to the given character limit,
|
Converts URLs into clickable links, truncating URLs to the given character
|
||||||
and adding 'rel=nofollow' attribute to discourage spamming.
|
limit, and adding 'rel=nofollow' attribute to discourage spamming.
|
||||||
|
|
||||||
Argument: Length to truncate URLs to.
|
Argument: Length to truncate URLs to.
|
||||||
"""
|
"""
|
||||||
|
@ -201,13 +206,13 @@ def urlizetrunc(value, limit):
|
||||||
urlizetrunc = stringfilter(urlizetrunc)
|
urlizetrunc = stringfilter(urlizetrunc)
|
||||||
|
|
||||||
def wordcount(value):
|
def wordcount(value):
|
||||||
"Returns the number of words"
|
"""Returns the number of words."""
|
||||||
return len(value.split())
|
return len(value.split())
|
||||||
wordcount = stringfilter(wordcount)
|
wordcount = stringfilter(wordcount)
|
||||||
|
|
||||||
def wordwrap(value, arg):
|
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.
|
Argument: number of characters to wrap the text at.
|
||||||
"""
|
"""
|
||||||
|
@ -217,29 +222,29 @@ wordwrap = stringfilter(wordwrap)
|
||||||
|
|
||||||
def ljust(value, arg):
|
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))
|
return value.ljust(int(arg))
|
||||||
ljust = stringfilter(ljust)
|
ljust = stringfilter(ljust)
|
||||||
|
|
||||||
def rjust(value, arg):
|
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))
|
return value.rjust(int(arg))
|
||||||
rjust = stringfilter(rjust)
|
rjust = stringfilter(rjust)
|
||||||
|
|
||||||
def center(value, arg):
|
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))
|
return value.center(int(arg))
|
||||||
center = stringfilter(center)
|
center = stringfilter(center)
|
||||||
|
|
||||||
def cut(value, arg):
|
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'')
|
return value.replace(arg, u'')
|
||||||
cut = stringfilter(cut)
|
cut = stringfilter(cut)
|
||||||
|
|
||||||
|
@ -272,7 +277,7 @@ def linebreaksbr(value):
|
||||||
linebreaksbr = stringfilter(linebreaksbr)
|
linebreaksbr = stringfilter(linebreaksbr)
|
||||||
|
|
||||||
def removetags(value, tags):
|
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.escape(tag) for tag in tags.split()]
|
||||||
tags_re = u'(%s)' % u'|'.join(tags)
|
tags_re = u'(%s)' % u'|'.join(tags)
|
||||||
starttag_re = re.compile(ur'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
|
starttag_re = re.compile(ur'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
|
||||||
|
@ -283,7 +288,7 @@ def removetags(value, tags):
|
||||||
removetags = stringfilter(removetags)
|
removetags = stringfilter(removetags)
|
||||||
|
|
||||||
def striptags(value):
|
def striptags(value):
|
||||||
"Strips all [X]HTML tags"
|
"""Strips all [X]HTML tags."""
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
return strip_tags(value)
|
return strip_tags(value)
|
||||||
striptags = stringfilter(striptags)
|
striptags = stringfilter(striptags)
|
||||||
|
@ -314,29 +319,29 @@ def dictsortreversed(value, arg):
|
||||||
return [item[1] for item in decorated]
|
return [item[1] for item in decorated]
|
||||||
|
|
||||||
def first(value):
|
def first(value):
|
||||||
"Returns the first item in a list"
|
"""Returns the first item in a list."""
|
||||||
try:
|
try:
|
||||||
return value[0]
|
return value[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return u''
|
return u''
|
||||||
|
|
||||||
def join(value, arg):
|
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:
|
try:
|
||||||
return arg.join(map(force_unicode, value))
|
return arg.join(map(force_unicode, value))
|
||||||
except AttributeError: # fail silently but nicely
|
except AttributeError: # fail silently but nicely
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def length(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)
|
return len(value)
|
||||||
|
|
||||||
def length_is(value, arg):
|
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)
|
return len(value) == int(arg)
|
||||||
|
|
||||||
def random(value):
|
def random(value):
|
||||||
"Returns a random item from the list"
|
"""Returns a random item from the list."""
|
||||||
return random_module.choice(value)
|
return random_module.choice(value)
|
||||||
|
|
||||||
def slice_(value, arg):
|
def slice_(value, arg):
|
||||||
|
@ -441,7 +446,7 @@ def unordered_list(value):
|
||||||
###################
|
###################
|
||||||
|
|
||||||
def add(value, arg):
|
def add(value, arg):
|
||||||
"Adds the arg to the value"
|
"""Adds the arg to the value."""
|
||||||
return int(value) + int(arg)
|
return int(value) + int(arg)
|
||||||
|
|
||||||
def get_digit(value, arg):
|
def get_digit(value, arg):
|
||||||
|
@ -468,7 +473,7 @@ def get_digit(value, arg):
|
||||||
###################
|
###################
|
||||||
|
|
||||||
def date(value, arg=None):
|
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
|
from django.utils.dateformat import format
|
||||||
if not value:
|
if not value:
|
||||||
return u''
|
return u''
|
||||||
|
@ -477,7 +482,7 @@ def date(value, arg=None):
|
||||||
return format(value, arg)
|
return format(value, arg)
|
||||||
|
|
||||||
def time(value, arg=None):
|
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
|
from django.utils.dateformat import time_format
|
||||||
if value in (None, u''):
|
if value in (None, u''):
|
||||||
return u''
|
return u''
|
||||||
|
@ -486,7 +491,7 @@ def time(value, arg=None):
|
||||||
return time_format(value, arg)
|
return time_format(value, arg)
|
||||||
|
|
||||||
def timesince(value, arg=None):
|
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
|
from django.utils.timesince import timesince
|
||||||
if not value:
|
if not value:
|
||||||
return u''
|
return u''
|
||||||
|
@ -495,7 +500,7 @@ def timesince(value, arg=None):
|
||||||
return timesince(value)
|
return timesince(value)
|
||||||
|
|
||||||
def timeuntil(value, arg=None):
|
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 django.utils.timesince import timesince
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
if not value:
|
if not value:
|
||||||
|
@ -509,17 +514,17 @@ def timeuntil(value, arg=None):
|
||||||
###################
|
###################
|
||||||
|
|
||||||
def default(value, arg):
|
def default(value, arg):
|
||||||
"If value is unavailable, use given default"
|
"""If value is unavailable, use given default."""
|
||||||
return value or arg
|
return value or arg
|
||||||
|
|
||||||
def default_if_none(value, 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:
|
if value is None:
|
||||||
return arg
|
return arg
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def divisibleby(value, arg):
|
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
|
return int(value) % int(arg) == 0
|
||||||
|
|
||||||
def yesno(value, arg=None):
|
def yesno(value, arg=None):
|
||||||
|
@ -544,7 +549,8 @@ def yesno(value, arg=None):
|
||||||
return value # Invalid arg.
|
return value # Invalid arg.
|
||||||
try:
|
try:
|
||||||
yes, no, maybe = bits
|
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]
|
yes, no, maybe = bits[0], bits[1], bits[1]
|
||||||
if value is None:
|
if value is None:
|
||||||
return maybe
|
return maybe
|
||||||
|
@ -558,8 +564,8 @@ def yesno(value, arg=None):
|
||||||
|
|
||||||
def filesizeformat(bytes):
|
def filesizeformat(bytes):
|
||||||
"""
|
"""
|
||||||
Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
|
Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB,
|
||||||
bytes, etc).
|
102 bytes, etc).
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
bytes = float(bytes)
|
bytes = float(bytes)
|
||||||
|
@ -591,23 +597,23 @@ def pluralize(value, arg=u's'):
|
||||||
try:
|
try:
|
||||||
if int(value) != 1:
|
if int(value) != 1:
|
||||||
return plural_suffix
|
return plural_suffix
|
||||||
except ValueError: # invalid string that's not a number
|
except ValueError: # Invalid string that's not a number.
|
||||||
pass
|
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:
|
try:
|
||||||
if len(value) != 1:
|
if len(value) != 1:
|
||||||
return plural_suffix
|
return plural_suffix
|
||||||
except TypeError: # len() of unsized object
|
except TypeError: # len() of unsized object.
|
||||||
pass
|
pass
|
||||||
return singular_suffix
|
return singular_suffix
|
||||||
|
|
||||||
def phone2numeric(value):
|
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
|
from django.utils.text import phone2numeric
|
||||||
return phone2numeric(value)
|
return phone2numeric(value)
|
||||||
|
|
||||||
def pprint(value):
|
def pprint(value):
|
||||||
"A wrapper around pprint.pprint -- for debugging, really"
|
"""A wrapper around pprint.pprint -- for debugging, really."""
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
try:
|
try:
|
||||||
return pformat(value)
|
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
|
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 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
|
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.conf import settings
|
||||||
from django.utils.encoding import smart_str, smart_unicode
|
from django.utils.encoding import smart_str, smart_unicode
|
||||||
from django.utils.itercompat import groupby
|
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()
|
register = Library()
|
||||||
|
|
||||||
|
@ -48,7 +47,7 @@ class FilterNode(Node):
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
output = self.nodelist.render(context)
|
output = self.nodelist.render(context)
|
||||||
# apply filters
|
# Apply filters.
|
||||||
context.update({'var': output})
|
context.update({'var': output})
|
||||||
filtered = self.filter_expr.resolve(context)
|
filtered = self.filter_expr.resolve(context)
|
||||||
context.pop()
|
context.pop()
|
||||||
|
@ -80,7 +79,8 @@ class ForNode(Node):
|
||||||
else:
|
else:
|
||||||
reversed = ''
|
reversed = ''
|
||||||
return "<For Node: for %s in %s, tail_len: %d%s>" % \
|
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):
|
def __iter__(self):
|
||||||
for node in self.nodelist_loop:
|
for node in self.nodelist_loop:
|
||||||
|
@ -114,19 +114,20 @@ class ForNode(Node):
|
||||||
unpack = len(self.loopvars) > 1
|
unpack = len(self.loopvars) > 1
|
||||||
for i, item in enumerate(values):
|
for i, item in enumerate(values):
|
||||||
context['forloop'] = {
|
context['forloop'] = {
|
||||||
# shortcuts for current loop iteration number
|
# Shortcuts for current loop iteration number.
|
||||||
'counter0': i,
|
'counter0': i,
|
||||||
'counter': i+1,
|
'counter': i+1,
|
||||||
# reverse counter iteration numbers
|
# Reverse counter iteration numbers.
|
||||||
'revcounter': len_values - i,
|
'revcounter': len_values - i,
|
||||||
'revcounter0': len_values - i - 1,
|
'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),
|
'first': (i == 0),
|
||||||
'last': (i == len_values - 1),
|
'last': (i == len_values - 1),
|
||||||
'parentloop': parentloop,
|
'parentloop': parentloop,
|
||||||
}
|
}
|
||||||
if unpack:
|
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)))
|
context.update(dict(zip(self.loopvars, item)))
|
||||||
else:
|
else:
|
||||||
context[self.loopvars[0]] = item
|
context[self.loopvars[0]] = item
|
||||||
|
@ -153,8 +154,8 @@ class IfChangedNode(Node):
|
||||||
self._last_seen = None
|
self._last_seen = None
|
||||||
try:
|
try:
|
||||||
if self._varlist:
|
if self._varlist:
|
||||||
# Consider multiple parameters.
|
# Consider multiple parameters. This automatically behaves
|
||||||
# This automatically behaves like a OR evaluation of the multiple variables.
|
# like an OR evaluation of the multiple variables.
|
||||||
compare_to = [var.resolve(context) for var in self._varlist]
|
compare_to = [var.resolve(context) for var in self._varlist]
|
||||||
else:
|
else:
|
||||||
compare_to = self.nodelist.render(context)
|
compare_to = self.nodelist.render(context)
|
||||||
|
@ -248,13 +249,17 @@ class RegroupNode(Node):
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
obj_list = self.target.resolve(context, True)
|
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] = []
|
context[self.var_name] = []
|
||||||
return ''
|
return ''
|
||||||
# List of dictionaries in the format
|
# List of dictionaries in the format:
|
||||||
# {'grouper': 'key', 'list': [list of contents]}.
|
# {'grouper': 'key', 'list': [list of contents]}.
|
||||||
context[self.var_name] = [{'grouper':key, 'list':list(val)} for key, val in
|
context[self.var_name] = [
|
||||||
groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))]
|
{'grouper': key, 'list': list(val)}
|
||||||
|
for key, val in
|
||||||
|
groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))
|
||||||
|
]
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def include_is_allowed(filepath):
|
def include_is_allowed(filepath):
|
||||||
|
@ -338,13 +343,15 @@ class URLNode(Node):
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
from django.core.urlresolvers import reverse, NoReverseMatch
|
from django.core.urlresolvers import reverse, NoReverseMatch
|
||||||
args = [arg.resolve(context) for arg in self.args]
|
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:
|
try:
|
||||||
return reverse(self.view_name, args=args, kwargs=kwargs)
|
return reverse(self.view_name, args=args, kwargs=kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
try:
|
try:
|
||||||
project_name = settings.SETTINGS_MODULE.split('.')[0]
|
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:
|
except NoReverseMatch:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
@ -388,7 +395,7 @@ class WithNode(Node):
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def comment(parser, token):
|
def comment(parser, token):
|
||||||
"""
|
"""
|
||||||
Ignore everything between ``{% comment %}`` and ``{% endcomment %}``
|
Ignores everything between ``{% comment %}`` and ``{% endcomment %}``.
|
||||||
"""
|
"""
|
||||||
parser.skip_past('endcomment')
|
parser.skip_past('endcomment')
|
||||||
return CommentNode()
|
return CommentNode()
|
||||||
|
@ -397,7 +404,7 @@ comment = register.tag(comment)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def cycle(parser, token):
|
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
|
Within a loop, cycles among the given strings each time through
|
||||||
the loop::
|
the loop::
|
||||||
|
@ -420,10 +427,10 @@ def cycle(parser, token):
|
||||||
interpreted as literal strings.
|
interpreted as literal strings.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Note: This returns the exact same node on each {% cycle name %} call; that
|
# Note: This returns the exact same node on each {% cycle name %} call;
|
||||||
# is, the node object returned from {% cycle a b c as name %} and the one
|
# that is, the node object returned from {% cycle a b c as name %} and the
|
||||||
# returned from {% cycle name %} are the exact same object. This shouldn't
|
# one returned from {% cycle name %} are the exact same object. This
|
||||||
# cause problems (heh), but if it does, now you know.
|
# shouldn't cause problems (heh), but if it does, now you know.
|
||||||
#
|
#
|
||||||
# Ugly hack warning: this stuffs the named template dict into parser so
|
# Ugly hack warning: this stuffs the named template dict into parser so
|
||||||
# that names are only unique within each template (as opposed to using
|
# 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(",")]
|
args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
|
||||||
|
|
||||||
if len(args) == 2:
|
if len(args) == 2:
|
||||||
# {% cycle foo %} case
|
# {% cycle foo %} case.
|
||||||
name = args[1]
|
name = args[1]
|
||||||
if not hasattr(parser, '_namedCycleNodes'):
|
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:
|
if not name in parser._namedCycleNodes:
|
||||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||||
return parser._namedCycleNodes[name]
|
return parser._namedCycleNodes[name]
|
||||||
|
@ -462,7 +470,8 @@ cycle = register.tag(cycle)
|
||||||
|
|
||||||
def debug(parser, token):
|
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::
|
Sample usage::
|
||||||
|
|
||||||
|
@ -476,7 +485,7 @@ debug = register.tag(debug)
|
||||||
#@register.tag(name="filter")
|
#@register.tag(name="filter")
|
||||||
def do_filter(parser, token):
|
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
|
Filters can also be piped through each other, and they can have
|
||||||
arguments -- just like in variable syntax.
|
arguments -- just like in variable syntax.
|
||||||
|
@ -525,14 +534,15 @@ def firstof(parser, token):
|
||||||
"""
|
"""
|
||||||
bits = token.split_contents()[1:]
|
bits = token.split_contents()[1:]
|
||||||
if len(bits) < 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)
|
return FirstOfNode(bits)
|
||||||
firstof = register.tag(firstof)
|
firstof = register.tag(firstof)
|
||||||
|
|
||||||
#@register.tag(name="for")
|
#@register.tag(name="for")
|
||||||
def do_for(parser, token):
|
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``::
|
For example, to display a list of athletes given ``athlete_list``::
|
||||||
|
|
||||||
|
@ -571,17 +581,20 @@ def do_for(parser, token):
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
if len(bits) < 4:
|
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'
|
reversed = bits[-1] == 'reversed'
|
||||||
in_index = reversed and -3 or -2
|
in_index = reversed and -3 or -2
|
||||||
if bits[in_index] != 'in':
|
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(',')
|
loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',')
|
||||||
for var in loopvars:
|
for var in loopvars:
|
||||||
if not var or ' ' in var:
|
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])
|
sequence = parser.compile_filter(bits[in_index+1])
|
||||||
nodelist_loop = parser.parse(('endfor',))
|
nodelist_loop = parser.parse(('endfor',))
|
||||||
|
@ -606,7 +619,7 @@ def do_ifequal(parser, token, negate):
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifequal(parser, token):
|
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::
|
Examples::
|
||||||
|
|
||||||
|
@ -625,7 +638,10 @@ ifequal = register.tag(ifequal)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifnotequal(parser, token):
|
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)
|
return do_ifequal(parser, token, True)
|
||||||
ifnotequal = register.tag(ifnotequal)
|
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"
|
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
|
(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 %}
|
{% if athlete_list %}
|
||||||
Number of athletes: {{ athlete_list|count }}
|
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
|
In the above, if ``athlete_list`` is not empty, the number of athletes will
|
||||||
be displayed by the ``{{ athlete_list|count }}`` variable.
|
be displayed by the ``{{ athlete_list|count }}`` variable.
|
||||||
|
|
||||||
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
As you can see, the ``if`` tag can take an option ``{% else %}`` clause
|
||||||
will be displayed if the test fails.
|
that will be displayed if the test fails.
|
||||||
|
|
||||||
``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
|
``if`` tags may use ``or``, ``and`` or ``not`` to test a number of
|
||||||
variables or to negate a given variable::
|
variables or to negate a given variable::
|
||||||
|
@ -673,9 +687,9 @@ def do_if(parser, token):
|
||||||
There are some athletes and absolutely no coaches.
|
There are some athletes and absolutely no coaches.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
``if`` tags do not allow ``and`` and ``or`` clauses with the same
|
``if`` tags do not allow ``and`` and ``or`` clauses with the same tag,
|
||||||
tag, because the order of logic would be ambigous. For example,
|
because the order of logic would be ambigous. For example, this is
|
||||||
this is invalid::
|
invalid::
|
||||||
|
|
||||||
{% if athlete_list and coach_list or cheerleader_list %}
|
{% if athlete_list and coach_list or cheerleader_list %}
|
||||||
|
|
||||||
|
@ -691,8 +705,8 @@ def do_if(parser, token):
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
del bits[0]
|
del bits[0]
|
||||||
if not bits:
|
if not bits:
|
||||||
raise TemplateSyntaxError, "'if' statement requires at least one argument"
|
raise TemplateSyntaxError("'if' statement requires at least one argument")
|
||||||
# bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
# Bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
||||||
bitstr = ' '.join(bits)
|
bitstr = ' '.join(bits)
|
||||||
boolpairs = bitstr.split(' and ')
|
boolpairs = bitstr.split(' and ')
|
||||||
boolvars = []
|
boolvars = []
|
||||||
|
@ -727,13 +741,13 @@ do_if = register.tag("if", do_if)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifchanged(parser, token):
|
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.
|
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
|
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
|
displays the content if it has changed. For example, this displays a
|
||||||
days, only displaying the month if it changes::
|
list of days, only displaying the month if it changes::
|
||||||
|
|
||||||
<h1>Archive for {{ year }}</h1>
|
<h1>Archive for {{ year }}</h1>
|
||||||
|
|
||||||
|
@ -742,9 +756,9 @@ def ifchanged(parser, token):
|
||||||
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
2. If given a variable, check whether that variable has changed. For example, the
|
2. If given a variable, check whether that variable has changed.
|
||||||
following shows the date every time it changes, but only shows the hour if both
|
For example, the following shows the date every time it changes, but
|
||||||
the hour and the date have changed::
|
only shows the hour if both the hour and the date have changed::
|
||||||
|
|
||||||
{% for date in days %}
|
{% for date in days %}
|
||||||
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
|
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
|
||||||
|
@ -762,7 +776,7 @@ ifchanged = register.tag(ifchanged)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ssi(parser, token):
|
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
|
Like a simple "include" tag, the ``ssi`` tag includes the contents
|
||||||
of another file -- which must be specified using an absolute page --
|
of another file -- which must be specified using an absolute page --
|
||||||
|
@ -778,21 +792,24 @@ def ssi(parser, token):
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
parsed = False
|
parsed = False
|
||||||
if len(bits) not in (2, 3):
|
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 len(bits) == 3:
|
||||||
if bits[2] == 'parsed':
|
if bits[2] == 'parsed':
|
||||||
parsed = True
|
parsed = True
|
||||||
else:
|
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)
|
return SsiNode(bits[1], parsed)
|
||||||
ssi = register.tag(ssi)
|
ssi = register.tag(ssi)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def load(parser, token):
|
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 %}
|
{% load news.photos %}
|
||||||
"""
|
"""
|
||||||
|
@ -803,14 +820,15 @@ def load(parser, token):
|
||||||
lib = get_library("django.templatetags.%s" % taglib)
|
lib = get_library("django.templatetags.%s" % taglib)
|
||||||
parser.add_library(lib)
|
parser.add_library(lib)
|
||||||
except InvalidTemplateLibrary, e:
|
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()
|
return LoadNode()
|
||||||
load = register.tag(load)
|
load = register.tag(load)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def now(parser, token):
|
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
|
Uses the same format as PHP's ``date()`` function; see http://php.net/date
|
||||||
for all the possible values.
|
for all the possible values.
|
||||||
|
@ -829,7 +847,7 @@ now = register.tag(now)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def regroup(parser, token):
|
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
|
This complex tag is best illustrated by use of an example: say that
|
||||||
``people`` is a list of ``Person`` objects that have ``first_name``,
|
``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
|
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
|
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
|
people was not sorted by gender, you'd need to make sure it is sorted
|
||||||
using it, i.e.::
|
before using it, i.e.::
|
||||||
|
|
||||||
{% regroup people|dictsort:"gender" by gender as grouped %}
|
{% regroup people|dictsort:"gender" by gender as grouped %}
|
||||||
|
|
||||||
|
@ -878,10 +896,11 @@ def regroup(parser, token):
|
||||||
raise TemplateSyntaxError, "'regroup' tag takes five arguments"
|
raise TemplateSyntaxError, "'regroup' tag takes five arguments"
|
||||||
target = parser.compile_filter(firstbits[1])
|
target = parser.compile_filter(firstbits[1])
|
||||||
if firstbits[2] != 'by':
|
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)
|
lastbits_reversed = firstbits[3][::-1].split(None, 2)
|
||||||
if lastbits_reversed[1][::-1] != 'as':
|
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])
|
expression = parser.compile_filter(lastbits_reversed[2][::-1])
|
||||||
|
|
||||||
|
@ -891,8 +910,7 @@ regroup = register.tag(regroup)
|
||||||
|
|
||||||
def spaceless(parser, token):
|
def spaceless(parser, token):
|
||||||
"""
|
"""
|
||||||
Removes whitespace between HTML tags. This includes tab
|
Removes whitespace between HTML tags, including tab and newline characters.
|
||||||
characters and newlines.
|
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
|
@ -906,8 +924,8 @@ def spaceless(parser, token):
|
||||||
|
|
||||||
<p><a href="foo/">Foo</a></p>
|
<p><a href="foo/">Foo</a></p>
|
||||||
|
|
||||||
Only space between *tags* is normalized -- not space between tags and text. In
|
Only space between *tags* is normalized -- not space between tags and text.
|
||||||
this example, the space around ``Hello`` won't be stripped::
|
In this example, the space around ``Hello`` won't be stripped::
|
||||||
|
|
||||||
{% spaceless %}
|
{% spaceless %}
|
||||||
<strong>
|
<strong>
|
||||||
|
@ -923,7 +941,7 @@ spaceless = register.tag(spaceless)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def templatetag(parser, token):
|
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
|
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.
|
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"
|
raise TemplateSyntaxError, "'templatetag' statement takes one argument"
|
||||||
tag = bits[1]
|
tag = bits[1]
|
||||||
if tag not in TemplateTagNode.mapping:
|
if tag not in TemplateTagNode.mapping:
|
||||||
raise TemplateSyntaxError, "Invalid templatetag argument: '%s'. Must be one of: %s" % \
|
raise TemplateSyntaxError("Invalid templatetag argument: '%s'."
|
||||||
(tag, TemplateTagNode.mapping.keys())
|
" Must be one of: %s" %
|
||||||
|
(tag, TemplateTagNode.mapping.keys()))
|
||||||
return TemplateTagNode(tag)
|
return TemplateTagNode(tag)
|
||||||
templatetag = register.tag(templatetag)
|
templatetag = register.tag(templatetag)
|
||||||
|
|
||||||
|
@ -957,7 +976,8 @@ def url(parser, token):
|
||||||
"""
|
"""
|
||||||
Returns an absolute URL matching given view with its parameters.
|
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 %}
|
{% url path.to.some_view arg1,arg2,name1=value1 %}
|
||||||
|
|
||||||
|
@ -985,7 +1005,8 @@ def url(parser, token):
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split(' ', 2)
|
bits = token.contents.split(' ', 2)
|
||||||
if len(bits) < 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 = []
|
args = []
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if len(bits) > 2:
|
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 %}' />
|
<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
|
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 *
|
the above example will be 88 pixels wide (because 175/200 = .875;
|
||||||
100 = 87.5 which is rounded up to 88).
|
.875 * 100 = 87.5 which is rounded up to 88).
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
if len(bits) != 4:
|
if len(bits) != 4:
|
||||||
|
@ -1028,7 +1049,7 @@ widthratio = register.tag(widthratio)
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def do_with(parser, token):
|
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.
|
access.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
@ -1039,7 +1060,8 @@ def do_with(parser, token):
|
||||||
"""
|
"""
|
||||||
bits = list(token.split_contents())
|
bits = list(token.split_contents())
|
||||||
if len(bits) != 4 or bits[2] != "as":
|
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])
|
var = parser.compile_filter(bits[1])
|
||||||
name = bits[3]
|
name = bits[3]
|
||||||
nodelist = parser.parse(('endwith',))
|
nodelist = parser.parse(('endwith',))
|
||||||
|
|
Loading…
Reference in New Issue