"""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, iri_to_uri from django.utils.safestring import mark_safe, SafeData register = Library() ####################### # STRING DECORATOR # ####################### def stringfilter(func): """ Decorator for filters which should only receive unicode objects. The object passed as the first positional argument will be converted to a unicode object. """ def _dec(*args, **kwargs): if args: args = list(args) args[0] = force_unicode(args[0]) if isinstance(args[0], SafeData) and getattr(func, 'is_safe', False): return mark_safe(func(*args, **kwargs)) return func(*args, **kwargs) # Include a reference to the real function (used to check original # arguments by the template parser). _dec._decorated_function = getattr(func, '_decorated_function', func) for attr in ('is_safe', 'needs_autoescape'): if hasattr(func, attr): setattr(_dec, attr, getattr(func, attr)) return _dec ################### # STRINGS # ################### def addslashes(value): """ Adds slashes before quotes. Useful for escaping strings in CSV, for example. Less useful for escaping JavaScript; use the ``escapejs`` filter instead. """ return value.replace('\\', '\\\\').replace('"', '\\"').replace("'", "\\'") addslashes.is_safe = True addslashes = stringfilter(addslashes) def capfirst(value): """Capitalizes the first character of the value.""" return value and value[0].upper() + value[1:] capfirst.is_safe=True capfirst = stringfilter(capfirst) _js_escapes = ( ('\\', '\\\\'), ('"', '\\"'), ("'", "\\'"), ('\n', '\\n'), ('\r', '\\r'), ('\b', '\\b'), ('\f', '\\f'), ('\t', '\\t'), ('\v', '\\v'), ('``) and a new line followed by a blank line becomes a paragraph break (``

``). """ from django.utils.html import linebreaks autoescape = autoescape and not isinstance(value, SafeData) return mark_safe(linebreaks(value, autoescape)) linebreaks.is_safe = True linebreaks.needs_autoescape = True linebreaks = stringfilter(linebreaks) def linebreaksbr(value, autoescape=None): """ Converts all newlines in a piece of plain text to HTML line breaks (``
``). """ if autoescape and not isinstance(value, SafeData): from django.utils.html import escape value = escape(value) return mark_safe(value.replace('\n', '
')) linebreaksbr.is_safe = True linebreaksbr.needs_autoescape = True linebreaksbr = stringfilter(linebreaksbr) def safe(value): """ Marks the value as a string that should not be auto-escaped. """ from django.utils.safestring import mark_safe return mark_safe(value) safe.is_safe = True safe = stringfilter(safe) def removetags(value, tags): """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) endtag_re = re.compile(u'' % tags_re) value = starttag_re.sub(u'', value) value = endtag_re.sub(u'', value) return value removetags.is_safe = True removetags = stringfilter(removetags) def striptags(value): """Strips all [X]HTML tags.""" from django.utils.html import strip_tags return strip_tags(value) striptags.is_safe = True striptags = stringfilter(striptags) ################### # LISTS # ################### def dictsort(value, arg): """ Takes a list of dicts, returns that list sorted by the property given in the argument. """ var_resolve = Variable(arg).resolve decorated = [(var_resolve(item), item) for item in value] decorated.sort() return [item[1] for item in decorated] dictsort.is_safe = False def dictsortreversed(value, arg): """ Takes a list of dicts, returns that list sorted in reverse order by the property given in the argument. """ var_resolve = Variable(arg).resolve decorated = [(var_resolve(item), item) for item in value] decorated.sort() decorated.reverse() return [item[1] for item in decorated] dictsortreversed.is_safe = False def first(value): """Returns the first item in a list.""" try: return value[0] except IndexError: return u'' first.is_safe = True def join(value, arg): """Joins a list with a string, like Python's ``str.join(list)``.""" try: data = arg.join(map(force_unicode, value)) except AttributeError: # fail silently but nicely return value safe_args = reduce(lambda lhs, rhs: lhs and isinstance(rhs, SafeData), value, True) if safe_args: return mark_safe(data) else: return data join.is_safe = True def length(value): """Returns the length of the value - useful for lists.""" return len(value) length.is_safe = True def length_is(value, arg): """Returns a boolean of whether the value's length is the argument.""" return len(value) == int(arg) length_is.is_safe = True def random(value): """Returns a random item from the list.""" return random_module.choice(value) random.is_safe = True def slice_(value, arg): """ Returns a slice of the list. Uses the same syntax as Python's list slicing; see http://diveintopython.org/native_data_types/lists.html#odbchelper.list.slice for an introduction. """ try: bits = [] for x in arg.split(u':'): if len(x) == 0: bits.append(None) else: bits.append(int(x)) return value[slice(*bits)] except (ValueError, TypeError): return value # Fail silently. slice_.is_safe = True def unordered_list(value, autoescape=None): """ Recursively takes a self-nested list and returns an HTML unordered list -- WITHOUT opening and closing