base.py 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354
  1. from __future__ import unicode_literals
  2. import re
  3. from functools import partial
  4. from importlib import import_module
  5. from inspect import getargspec, getcallargs
  6. from django.apps import apps
  7. from django.conf import settings
  8. from django.template.context import (BaseContext, Context, RequestContext, # NOQA: imported for backwards compatibility
  9. ContextPopException)
  10. from django.utils.itercompat import is_iterable
  11. from django.utils.text import (smart_split, unescape_string_literal,
  12. get_text_list)
  13. from django.utils.encoding import force_str, force_text
  14. from django.utils.translation import ugettext_lazy, pgettext_lazy
  15. from django.utils.safestring import (SafeData, EscapeData, mark_safe,
  16. mark_for_escaping)
  17. from django.utils.formats import localize
  18. from django.utils.html import escape
  19. from django.utils.module_loading import module_has_submodule
  20. from django.utils import six
  21. from django.utils.timezone import template_localtime
  22. from django.utils.encoding import python_2_unicode_compatible
  23. TOKEN_TEXT = 0
  24. TOKEN_VAR = 1
  25. TOKEN_BLOCK = 2
  26. TOKEN_COMMENT = 3
  27. TOKEN_MAPPING = {
  28. TOKEN_TEXT: 'Text',
  29. TOKEN_VAR: 'Var',
  30. TOKEN_BLOCK: 'Block',
  31. TOKEN_COMMENT: 'Comment',
  32. }
  33. # template syntax constants
  34. FILTER_SEPARATOR = '|'
  35. FILTER_ARGUMENT_SEPARATOR = ':'
  36. VARIABLE_ATTRIBUTE_SEPARATOR = '.'
  37. BLOCK_TAG_START = '{%'
  38. BLOCK_TAG_END = '%}'
  39. VARIABLE_TAG_START = '{{'
  40. VARIABLE_TAG_END = '}}'
  41. COMMENT_TAG_START = '{#'
  42. COMMENT_TAG_END = '#}'
  43. TRANSLATOR_COMMENT_MARK = 'Translators'
  44. SINGLE_BRACE_START = '{'
  45. SINGLE_BRACE_END = '}'
  46. ALLOWED_VARIABLE_CHARS = ('abcdefghijklmnopqrstuvwxyz'
  47. 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.')
  48. # what to report as the origin for templates that come from non-loader sources
  49. # (e.g. strings)
  50. UNKNOWN_SOURCE = '<unknown source>'
  51. # match a variable or block tag and capture the entire tag, including start/end
  52. # delimiters
  53. tag_re = (re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' %
  54. (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
  55. re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
  56. re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END))))
  57. # global dictionary of libraries that have been loaded using get_library
  58. libraries = {}
  59. # global list of libraries to load by default for a new parser
  60. builtins = []
  61. # True if TEMPLATE_STRING_IF_INVALID contains a format string (%s). None means
  62. # uninitialized.
  63. invalid_var_format_string = None
  64. class TemplateSyntaxError(Exception):
  65. pass
  66. class TemplateDoesNotExist(Exception):
  67. pass
  68. class TemplateEncodingError(Exception):
  69. pass
  70. @python_2_unicode_compatible
  71. class VariableDoesNotExist(Exception):
  72. def __init__(self, msg, params=()):
  73. self.msg = msg
  74. self.params = params
  75. def __str__(self):
  76. return self.msg % tuple(force_text(p, errors='replace') for p in self.params)
  77. class InvalidTemplateLibrary(Exception):
  78. pass
  79. class Origin(object):
  80. def __init__(self, name):
  81. self.name = name
  82. def reload(self):
  83. raise NotImplementedError('subclasses of Origin must provide a reload() method')
  84. def __str__(self):
  85. return self.name
  86. class StringOrigin(Origin):
  87. def __init__(self, source):
  88. super(StringOrigin, self).__init__(UNKNOWN_SOURCE)
  89. self.source = source
  90. def reload(self):
  91. return self.source
  92. class Template(object):
  93. def __init__(self, template_string, origin=None, name=None):
  94. try:
  95. template_string = force_text(template_string)
  96. except UnicodeDecodeError:
  97. raise TemplateEncodingError("Templates can only be constructed "
  98. "from unicode or UTF-8 strings.")
  99. if settings.TEMPLATE_DEBUG and origin is None:
  100. origin = StringOrigin(template_string)
  101. self.nodelist = compile_string(template_string, origin)
  102. self.name = name
  103. self.origin = origin
  104. def __iter__(self):
  105. for node in self.nodelist:
  106. for subnode in node:
  107. yield subnode
  108. def _render(self, context):
  109. return self.nodelist.render(context)
  110. def render(self, context):
  111. "Display stage -- can be called many times"
  112. context.render_context.push()
  113. try:
  114. return self._render(context)
  115. finally:
  116. context.render_context.pop()
  117. def compile_string(template_string, origin):
  118. "Compiles template_string into NodeList ready for rendering"
  119. if settings.TEMPLATE_DEBUG:
  120. from django.template.debug import DebugLexer, DebugParser
  121. lexer_class, parser_class = DebugLexer, DebugParser
  122. else:
  123. lexer_class, parser_class = Lexer, Parser
  124. lexer = lexer_class(template_string, origin)
  125. parser = parser_class(lexer.tokenize())
  126. return parser.parse()
  127. class Token(object):
  128. def __init__(self, token_type, contents):
  129. # token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or
  130. # TOKEN_COMMENT.
  131. self.token_type, self.contents = token_type, contents
  132. self.lineno = None
  133. def __str__(self):
  134. token_name = TOKEN_MAPPING[self.token_type]
  135. return ('<%s token: "%s...">' %
  136. (token_name, self.contents[:20].replace('\n', '')))
  137. def split_contents(self):
  138. split = []
  139. bits = iter(smart_split(self.contents))
  140. for bit in bits:
  141. # Handle translation-marked template pieces
  142. if bit.startswith('_("') or bit.startswith("_('"):
  143. sentinal = bit[2] + ')'
  144. trans_bit = [bit]
  145. while not bit.endswith(sentinal):
  146. bit = next(bits)
  147. trans_bit.append(bit)
  148. bit = ' '.join(trans_bit)
  149. split.append(bit)
  150. return split
  151. class Lexer(object):
  152. def __init__(self, template_string, origin):
  153. self.template_string = template_string
  154. self.origin = origin
  155. self.lineno = 1
  156. self.verbatim = False
  157. def tokenize(self):
  158. """
  159. Return a list of tokens from a given template_string.
  160. """
  161. in_tag = False
  162. result = []
  163. for bit in tag_re.split(self.template_string):
  164. if bit:
  165. result.append(self.create_token(bit, in_tag))
  166. in_tag = not in_tag
  167. return result
  168. def create_token(self, token_string, in_tag):
  169. """
  170. Convert the given token string into a new Token object and return it.
  171. If in_tag is True, we are processing something that matched a tag,
  172. otherwise it should be treated as a literal string.
  173. """
  174. if in_tag and token_string.startswith(BLOCK_TAG_START):
  175. # The [2:-2] ranges below strip off *_TAG_START and *_TAG_END.
  176. # We could do len(BLOCK_TAG_START) to be more "correct", but we've
  177. # hard-coded the 2s here for performance. And it's not like
  178. # the TAG_START values are going to change anytime, anyway.
  179. block_content = token_string[2:-2].strip()
  180. if self.verbatim and block_content == self.verbatim:
  181. self.verbatim = False
  182. if in_tag and not self.verbatim:
  183. if token_string.startswith(VARIABLE_TAG_START):
  184. token = Token(TOKEN_VAR, token_string[2:-2].strip())
  185. elif token_string.startswith(BLOCK_TAG_START):
  186. if block_content[:9] in ('verbatim', 'verbatim '):
  187. self.verbatim = 'end%s' % block_content
  188. token = Token(TOKEN_BLOCK, block_content)
  189. elif token_string.startswith(COMMENT_TAG_START):
  190. content = ''
  191. if token_string.find(TRANSLATOR_COMMENT_MARK):
  192. content = token_string[2:-2].strip()
  193. token = Token(TOKEN_COMMENT, content)
  194. else:
  195. token = Token(TOKEN_TEXT, token_string)
  196. token.lineno = self.lineno
  197. self.lineno += token_string.count('\n')
  198. return token
  199. class Parser(object):
  200. def __init__(self, tokens):
  201. self.tokens = tokens
  202. self.tags = {}
  203. self.filters = {}
  204. for lib in builtins:
  205. self.add_library(lib)
  206. def parse(self, parse_until=None):
  207. if parse_until is None:
  208. parse_until = []
  209. nodelist = self.create_nodelist()
  210. while self.tokens:
  211. token = self.next_token()
  212. # Use the raw values here for TOKEN_* for a tiny performance boost.
  213. if token.token_type == 0: # TOKEN_TEXT
  214. self.extend_nodelist(nodelist, TextNode(token.contents), token)
  215. elif token.token_type == 1: # TOKEN_VAR
  216. if not token.contents:
  217. self.empty_variable(token)
  218. try:
  219. filter_expression = self.compile_filter(token.contents)
  220. except TemplateSyntaxError as e:
  221. if not self.compile_filter_error(token, e):
  222. raise
  223. var_node = self.create_variable_node(filter_expression)
  224. self.extend_nodelist(nodelist, var_node, token)
  225. elif token.token_type == 2: # TOKEN_BLOCK
  226. try:
  227. command = token.contents.split()[0]
  228. except IndexError:
  229. self.empty_block_tag(token)
  230. if command in parse_until:
  231. # put token back on token list so calling
  232. # code knows why it terminated
  233. self.prepend_token(token)
  234. return nodelist
  235. # execute callback function for this tag and append
  236. # resulting node
  237. self.enter_command(command, token)
  238. try:
  239. compile_func = self.tags[command]
  240. except KeyError:
  241. self.invalid_block_tag(token, command, parse_until)
  242. try:
  243. compiled_result = compile_func(self, token)
  244. except TemplateSyntaxError as e:
  245. if not self.compile_function_error(token, e):
  246. raise
  247. self.extend_nodelist(nodelist, compiled_result, token)
  248. self.exit_command()
  249. if parse_until:
  250. self.unclosed_block_tag(parse_until)
  251. return nodelist
  252. def skip_past(self, endtag):
  253. while self.tokens:
  254. token = self.next_token()
  255. if token.token_type == TOKEN_BLOCK and token.contents == endtag:
  256. return
  257. self.unclosed_block_tag([endtag])
  258. def create_variable_node(self, filter_expression):
  259. return VariableNode(filter_expression)
  260. def create_nodelist(self):
  261. return NodeList()
  262. def extend_nodelist(self, nodelist, node, token):
  263. if node.must_be_first and nodelist:
  264. try:
  265. if nodelist.contains_nontext:
  266. raise AttributeError
  267. except AttributeError:
  268. raise TemplateSyntaxError("%r must be the first tag "
  269. "in the template." % node)
  270. if isinstance(nodelist, NodeList) and not isinstance(node, TextNode):
  271. nodelist.contains_nontext = True
  272. nodelist.append(node)
  273. def enter_command(self, command, token):
  274. pass
  275. def exit_command(self):
  276. pass
  277. def error(self, token, msg):
  278. return TemplateSyntaxError(msg)
  279. def empty_variable(self, token):
  280. raise self.error(token, "Empty variable tag")
  281. def empty_block_tag(self, token):
  282. raise self.error(token, "Empty block tag")
  283. def invalid_block_tag(self, token, command, parse_until=None):
  284. if parse_until:
  285. raise self.error(token, "Invalid block tag: '%s', expected %s" %
  286. (command, get_text_list(["'%s'" % p for p in parse_until])))
  287. raise self.error(token, "Invalid block tag: '%s'" % command)
  288. def unclosed_block_tag(self, parse_until):
  289. raise self.error(None, "Unclosed tags: %s " % ', '.join(parse_until))
  290. def compile_filter_error(self, token, e):
  291. pass
  292. def compile_function_error(self, token, e):
  293. pass
  294. def next_token(self):
  295. return self.tokens.pop(0)
  296. def prepend_token(self, token):
  297. self.tokens.insert(0, token)
  298. def delete_first_token(self):
  299. del self.tokens[0]
  300. def add_library(self, lib):
  301. self.tags.update(lib.tags)
  302. self.filters.update(lib.filters)
  303. def compile_filter(self, token):
  304. """
  305. Convenient wrapper for FilterExpression
  306. """
  307. return FilterExpression(token, self)
  308. def find_filter(self, filter_name):
  309. if filter_name in self.filters:
  310. return self.filters[filter_name]
  311. else:
  312. raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
  313. class TokenParser(object):
  314. """
  315. Subclass this and implement the top() method to parse a template line.
  316. When instantiating the parser, pass in the line from the Django template
  317. parser.
  318. The parser's "tagname" instance-variable stores the name of the tag that
  319. the filter was called with.
  320. """
  321. def __init__(self, subject):
  322. self.subject = subject
  323. self.pointer = 0
  324. self.backout = []
  325. self.tagname = self.tag()
  326. def top(self):
  327. """
  328. Overload this method to do the actual parsing and return the result.
  329. """
  330. raise NotImplementedError('subclasses of Tokenparser must provide a top() method')
  331. def more(self):
  332. """
  333. Returns True if there is more stuff in the tag.
  334. """
  335. return self.pointer < len(self.subject)
  336. def back(self):
  337. """
  338. Undoes the last microparser. Use this for lookahead and backtracking.
  339. """
  340. if not len(self.backout):
  341. raise TemplateSyntaxError("back called without some previous "
  342. "parsing")
  343. self.pointer = self.backout.pop()
  344. def tag(self):
  345. """
  346. A microparser that just returns the next tag from the line.
  347. """
  348. subject = self.subject
  349. i = self.pointer
  350. if i >= len(subject):
  351. raise TemplateSyntaxError("expected another tag, found "
  352. "end of string: %s" % subject)
  353. p = i
  354. while i < len(subject) and subject[i] not in (' ', '\t'):
  355. i += 1
  356. s = subject[p:i]
  357. while i < len(subject) and subject[i] in (' ', '\t'):
  358. i += 1
  359. self.backout.append(self.pointer)
  360. self.pointer = i
  361. return s
  362. def value(self):
  363. """
  364. A microparser that parses for a value: some string constant or
  365. variable name.
  366. """
  367. subject = self.subject
  368. i = self.pointer
  369. def next_space_index(subject, i):
  370. """
  371. Increment pointer until a real space (i.e. a space not within
  372. quotes) is encountered
  373. """
  374. while i < len(subject) and subject[i] not in (' ', '\t'):
  375. if subject[i] in ('"', "'"):
  376. c = subject[i]
  377. i += 1
  378. while i < len(subject) and subject[i] != c:
  379. i += 1
  380. if i >= len(subject):
  381. raise TemplateSyntaxError("Searching for value. "
  382. "Unexpected end of string in column %d: %s" %
  383. (i, subject))
  384. i += 1
  385. return i
  386. if i >= len(subject):
  387. raise TemplateSyntaxError("Searching for value. Expected another "
  388. "value but found end of string: %s" %
  389. subject)
  390. if subject[i] in ('"', "'"):
  391. p = i
  392. i += 1
  393. while i < len(subject) and subject[i] != subject[p]:
  394. i += 1
  395. if i >= len(subject):
  396. raise TemplateSyntaxError("Searching for value. Unexpected "
  397. "end of string in column %d: %s" %
  398. (i, subject))
  399. i += 1
  400. # Continue parsing until next "real" space,
  401. # so that filters are also included
  402. i = next_space_index(subject, i)
  403. res = subject[p:i]
  404. while i < len(subject) and subject[i] in (' ', '\t'):
  405. i += 1
  406. self.backout.append(self.pointer)
  407. self.pointer = i
  408. return res
  409. else:
  410. p = i
  411. i = next_space_index(subject, i)
  412. s = subject[p:i]
  413. while i < len(subject) and subject[i] in (' ', '\t'):
  414. i += 1
  415. self.backout.append(self.pointer)
  416. self.pointer = i
  417. return s
  418. # This only matches constant *strings* (things in quotes or marked for
  419. # translation). Numbers are treated as variables for implementation reasons
  420. # (so that they retain their type when passed to filters).
  421. constant_string = r"""
  422. (?:%(i18n_open)s%(strdq)s%(i18n_close)s|
  423. %(i18n_open)s%(strsq)s%(i18n_close)s|
  424. %(strdq)s|
  425. %(strsq)s)
  426. """ % {
  427. 'strdq': r'"[^"\\]*(?:\\.[^"\\]*)*"', # double-quoted string
  428. 'strsq': r"'[^'\\]*(?:\\.[^'\\]*)*'", # single-quoted string
  429. 'i18n_open': re.escape("_("),
  430. 'i18n_close': re.escape(")"),
  431. }
  432. constant_string = constant_string.replace("\n", "")
  433. filter_raw_string = r"""
  434. ^(?P<constant>%(constant)s)|
  435. ^(?P<var>[%(var_chars)s]+|%(num)s)|
  436. (?:\s*%(filter_sep)s\s*
  437. (?P<filter_name>\w+)
  438. (?:%(arg_sep)s
  439. (?:
  440. (?P<constant_arg>%(constant)s)|
  441. (?P<var_arg>[%(var_chars)s]+|%(num)s)
  442. )
  443. )?
  444. )""" % {
  445. 'constant': constant_string,
  446. 'num': r'[-+\.]?\d[\d\.e]*',
  447. 'var_chars': "\w\.",
  448. 'filter_sep': re.escape(FILTER_SEPARATOR),
  449. 'arg_sep': re.escape(FILTER_ARGUMENT_SEPARATOR),
  450. }
  451. filter_re = re.compile(filter_raw_string, re.UNICODE | re.VERBOSE)
  452. class FilterExpression(object):
  453. """
  454. Parses a variable token and its optional filters (all as a single string),
  455. and return a list of tuples of the filter name and arguments.
  456. Sample::
  457. >>> token = 'variable|default:"Default value"|date:"Y-m-d"'
  458. >>> p = Parser('')
  459. >>> fe = FilterExpression(token, p)
  460. >>> len(fe.filters)
  461. 2
  462. >>> fe.var
  463. <Variable: 'variable'>
  464. """
  465. def __init__(self, token, parser):
  466. self.token = token
  467. matches = filter_re.finditer(token)
  468. var_obj = None
  469. filters = []
  470. upto = 0
  471. for match in matches:
  472. start = match.start()
  473. if upto != start:
  474. raise TemplateSyntaxError("Could not parse some characters: "
  475. "%s|%s|%s" %
  476. (token[:upto], token[upto:start],
  477. token[start:]))
  478. if var_obj is None:
  479. var, constant = match.group("var", "constant")
  480. if constant:
  481. try:
  482. var_obj = Variable(constant).resolve({})
  483. except VariableDoesNotExist:
  484. var_obj = None
  485. elif var is None:
  486. raise TemplateSyntaxError("Could not find variable at "
  487. "start of %s." % token)
  488. else:
  489. var_obj = Variable(var)
  490. else:
  491. filter_name = match.group("filter_name")
  492. args = []
  493. constant_arg, var_arg = match.group("constant_arg", "var_arg")
  494. if constant_arg:
  495. args.append((False, Variable(constant_arg).resolve({})))
  496. elif var_arg:
  497. args.append((True, Variable(var_arg)))
  498. filter_func = parser.find_filter(filter_name)
  499. self.args_check(filter_name, filter_func, args)
  500. filters.append((filter_func, args))
  501. upto = match.end()
  502. if upto != len(token):
  503. raise TemplateSyntaxError("Could not parse the remainder: '%s' "
  504. "from '%s'" % (token[upto:], token))
  505. self.filters = filters
  506. self.var = var_obj
  507. def resolve(self, context, ignore_failures=False):
  508. if isinstance(self.var, Variable):
  509. try:
  510. obj = self.var.resolve(context)
  511. except VariableDoesNotExist:
  512. if ignore_failures:
  513. obj = None
  514. else:
  515. if settings.TEMPLATE_STRING_IF_INVALID:
  516. global invalid_var_format_string
  517. if invalid_var_format_string is None:
  518. invalid_var_format_string = '%s' in settings.TEMPLATE_STRING_IF_INVALID
  519. if invalid_var_format_string:
  520. return settings.TEMPLATE_STRING_IF_INVALID % self.var
  521. return settings.TEMPLATE_STRING_IF_INVALID
  522. else:
  523. obj = settings.TEMPLATE_STRING_IF_INVALID
  524. else:
  525. obj = self.var
  526. for func, args in self.filters:
  527. arg_vals = []
  528. for lookup, arg in args:
  529. if not lookup:
  530. arg_vals.append(mark_safe(arg))
  531. else:
  532. arg_vals.append(arg.resolve(context))
  533. if getattr(func, 'expects_localtime', False):
  534. obj = template_localtime(obj, context.use_tz)
  535. if getattr(func, 'needs_autoescape', False):
  536. new_obj = func(obj, autoescape=context.autoescape, *arg_vals)
  537. else:
  538. new_obj = func(obj, *arg_vals)
  539. if getattr(func, 'is_safe', False) and isinstance(obj, SafeData):
  540. obj = mark_safe(new_obj)
  541. elif isinstance(obj, EscapeData):
  542. obj = mark_for_escaping(new_obj)
  543. else:
  544. obj = new_obj
  545. return obj
  546. def args_check(name, func, provided):
  547. provided = list(provided)
  548. # First argument, filter input, is implied.
  549. plen = len(provided) + 1
  550. # Check to see if a decorator is providing the real function.
  551. func = getattr(func, '_decorated_function', func)
  552. args, varargs, varkw, defaults = getargspec(func)
  553. alen = len(args)
  554. dlen = len(defaults or [])
  555. # Not enough OR Too many
  556. if plen < (alen - dlen) or plen > alen:
  557. raise TemplateSyntaxError("%s requires %d arguments, %d provided" %
  558. (name, alen - dlen, plen))
  559. return True
  560. args_check = staticmethod(args_check)
  561. def __str__(self):
  562. return self.token
  563. def resolve_variable(path, context):
  564. """
  565. Returns the resolved variable, which may contain attribute syntax, within
  566. the given context.
  567. Deprecated; use the Variable class instead.
  568. """
  569. return Variable(path).resolve(context)
  570. class Variable(object):
  571. """
  572. A template variable, resolvable against a given context. The variable may
  573. be a hard-coded string (if it begins and ends with single or double quote
  574. marks)::
  575. >>> c = {'article': {'section':u'News'}}
  576. >>> Variable('article.section').resolve(c)
  577. u'News'
  578. >>> Variable('article').resolve(c)
  579. {'section': u'News'}
  580. >>> class AClass: pass
  581. >>> c = AClass()
  582. >>> c.article = AClass()
  583. >>> c.article.section = u'News'
  584. (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
  585. """
  586. def __init__(self, var):
  587. self.var = var
  588. self.literal = None
  589. self.lookups = None
  590. self.translate = False
  591. self.message_context = None
  592. if not isinstance(var, six.string_types):
  593. raise TypeError(
  594. "Variable must be a string or number, got %s" % type(var))
  595. try:
  596. # First try to treat this variable as a number.
  597. #
  598. # Note that this could cause an OverflowError here that we're not
  599. # catching. Since this should only happen at compile time, that's
  600. # probably OK.
  601. self.literal = float(var)
  602. # So it's a float... is it an int? If the original value contained a
  603. # dot or an "e" then it was a float, not an int.
  604. if '.' not in var and 'e' not in var.lower():
  605. self.literal = int(self.literal)
  606. # "2." is invalid
  607. if var.endswith('.'):
  608. raise ValueError
  609. except ValueError:
  610. # A ValueError means that the variable isn't a number.
  611. if var.startswith('_(') and var.endswith(')'):
  612. # The result of the lookup should be translated at rendering
  613. # time.
  614. self.translate = True
  615. var = var[2:-1]
  616. # If it's wrapped with quotes (single or double), then
  617. # we're also dealing with a literal.
  618. try:
  619. self.literal = mark_safe(unescape_string_literal(var))
  620. except ValueError:
  621. # Otherwise we'll set self.lookups so that resolve() knows we're
  622. # dealing with a bonafide variable
  623. if var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_':
  624. raise TemplateSyntaxError("Variables and attributes may "
  625. "not begin with underscores: '%s'" %
  626. var)
  627. self.lookups = tuple(var.split(VARIABLE_ATTRIBUTE_SEPARATOR))
  628. def resolve(self, context):
  629. """Resolve this variable against a given context."""
  630. if self.lookups is not None:
  631. # We're dealing with a variable that needs to be resolved
  632. value = self._resolve_lookup(context)
  633. else:
  634. # We're dealing with a literal, so it's already been "resolved"
  635. value = self.literal
  636. if self.translate:
  637. if self.message_context:
  638. return pgettext_lazy(self.message_context, value)
  639. else:
  640. return ugettext_lazy(value)
  641. return value
  642. def __repr__(self):
  643. return "<%s: %r>" % (self.__class__.__name__, self.var)
  644. def __str__(self):
  645. return self.var
  646. def _resolve_lookup(self, context):
  647. """
  648. Performs resolution of a real variable (i.e. not a literal) against the
  649. given context.
  650. As indicated by the method's name, this method is an implementation
  651. detail and shouldn't be called by external code. Use Variable.resolve()
  652. instead.
  653. """
  654. current = context
  655. try: # catch-all for silent variable failures
  656. for bit in self.lookups:
  657. try: # dictionary lookup
  658. current = current[bit]
  659. except (TypeError, AttributeError, KeyError, ValueError):
  660. try: # attribute lookup
  661. # Don't return class attributes if the class is the context:
  662. if isinstance(current, BaseContext) and getattr(type(current), bit):
  663. raise AttributeError
  664. current = getattr(current, bit)
  665. except (TypeError, AttributeError):
  666. try: # list-index lookup
  667. current = current[int(bit)]
  668. except (IndexError, # list index out of range
  669. ValueError, # invalid literal for int()
  670. KeyError, # current is a dict without `int(bit)` key
  671. TypeError): # unsubscriptable object
  672. raise VariableDoesNotExist("Failed lookup for key "
  673. "[%s] in %r",
  674. (bit, current)) # missing attribute
  675. if callable(current):
  676. if getattr(current, 'do_not_call_in_templates', False):
  677. pass
  678. elif getattr(current, 'alters_data', False):
  679. current = settings.TEMPLATE_STRING_IF_INVALID
  680. else:
  681. try: # method call (assuming no args required)
  682. current = current()
  683. except TypeError:
  684. try:
  685. getcallargs(current)
  686. except TypeError: # arguments *were* required
  687. current = settings.TEMPLATE_STRING_IF_INVALID # invalid method call
  688. else:
  689. raise
  690. except Exception as e:
  691. if getattr(e, 'silent_variable_failure', False):
  692. current = settings.TEMPLATE_STRING_IF_INVALID
  693. else:
  694. raise
  695. return current
  696. class Node(object):
  697. # Set this to True for nodes that must be first in the template (although
  698. # they can be preceded by text nodes.
  699. must_be_first = False
  700. child_nodelists = ('nodelist',)
  701. def render(self, context):
  702. """
  703. Return the node rendered as a string.
  704. """
  705. pass
  706. def __iter__(self):
  707. yield self
  708. def get_nodes_by_type(self, nodetype):
  709. """
  710. Return a list of all nodes (within this node and its nodelist)
  711. of the given type
  712. """
  713. nodes = []
  714. if isinstance(self, nodetype):
  715. nodes.append(self)
  716. for attr in self.child_nodelists:
  717. nodelist = getattr(self, attr, None)
  718. if nodelist:
  719. nodes.extend(nodelist.get_nodes_by_type(nodetype))
  720. return nodes
  721. class NodeList(list):
  722. # Set to True the first time a non-TextNode is inserted by
  723. # extend_nodelist().
  724. contains_nontext = False
  725. def render(self, context):
  726. bits = []
  727. for node in self:
  728. if isinstance(node, Node):
  729. bit = self.render_node(node, context)
  730. else:
  731. bit = node
  732. bits.append(force_text(bit))
  733. return mark_safe(''.join(bits))
  734. def get_nodes_by_type(self, nodetype):
  735. "Return a list of all nodes of the given type"
  736. nodes = []
  737. for node in self:
  738. nodes.extend(node.get_nodes_by_type(nodetype))
  739. return nodes
  740. def render_node(self, node, context):
  741. return node.render(context)
  742. class TextNode(Node):
  743. def __init__(self, s):
  744. self.s = s
  745. def __repr__(self):
  746. return force_str("<Text Node: '%s'>" % self.s[:25], 'ascii',
  747. errors='replace')
  748. def render(self, context):
  749. return self.s
  750. def render_value_in_context(value, context):
  751. """
  752. Converts any value to a string to become part of a rendered template. This
  753. means escaping, if required, and conversion to a unicode object. If value
  754. is a string, it is expected to have already been translated.
  755. """
  756. value = template_localtime(value, use_tz=context.use_tz)
  757. value = localize(value, use_l10n=context.use_l10n)
  758. value = force_text(value)
  759. if ((context.autoescape and not isinstance(value, SafeData)) or
  760. isinstance(value, EscapeData)):
  761. return escape(value)
  762. else:
  763. return value
  764. class VariableNode(Node):
  765. def __init__(self, filter_expression):
  766. self.filter_expression = filter_expression
  767. def __repr__(self):
  768. return "<Variable Node: %s>" % self.filter_expression
  769. def render(self, context):
  770. try:
  771. output = self.filter_expression.resolve(context)
  772. except UnicodeDecodeError:
  773. # Unicode conversion can fail sometimes for reasons out of our
  774. # control (e.g. exception rendering). In that case, we fail
  775. # quietly.
  776. return ''
  777. return render_value_in_context(output, context)
  778. # Regex for token keyword arguments
  779. kwarg_re = re.compile(r"(?:(\w+)=)?(.+)")
  780. def token_kwargs(bits, parser, support_legacy=False):
  781. """
  782. A utility method for parsing token keyword arguments.
  783. :param bits: A list containing remainder of the token (split by spaces)
  784. that is to be checked for arguments. Valid arguments will be removed
  785. from this list.
  786. :param support_legacy: If set to true ``True``, the legacy format
  787. ``1 as foo`` will be accepted. Otherwise, only the standard ``foo=1``
  788. format is allowed.
  789. :returns: A dictionary of the arguments retrieved from the ``bits`` token
  790. list.
  791. There is no requirement for all remaining token ``bits`` to be keyword
  792. arguments, so the dictionary will be returned as soon as an invalid
  793. argument format is reached.
  794. """
  795. if not bits:
  796. return {}
  797. match = kwarg_re.match(bits[0])
  798. kwarg_format = match and match.group(1)
  799. if not kwarg_format:
  800. if not support_legacy:
  801. return {}
  802. if len(bits) < 3 or bits[1] != 'as':
  803. return {}
  804. kwargs = {}
  805. while bits:
  806. if kwarg_format:
  807. match = kwarg_re.match(bits[0])
  808. if not match or not match.group(1):
  809. return kwargs
  810. key, value = match.groups()
  811. del bits[:1]
  812. else:
  813. if len(bits) < 3 or bits[1] != 'as':
  814. return kwargs
  815. key, value = bits[2], bits[0]
  816. del bits[:3]
  817. kwargs[key] = parser.compile_filter(value)
  818. if bits and not kwarg_format:
  819. if bits[0] != 'and':
  820. return kwargs
  821. del bits[:1]
  822. return kwargs
  823. def parse_bits(parser, bits, params, varargs, varkw, defaults,
  824. takes_context, name):
  825. """
  826. Parses bits for template tag helpers (simple_tag, include_tag and
  827. assignment_tag), in particular by detecting syntax errors and by
  828. extracting positional and keyword arguments.
  829. """
  830. if takes_context:
  831. if params[0] == 'context':
  832. params = params[1:]
  833. else:
  834. raise TemplateSyntaxError(
  835. "'%s' is decorated with takes_context=True so it must "
  836. "have a first argument of 'context'" % name)
  837. args = []
  838. kwargs = {}
  839. unhandled_params = list(params)
  840. for bit in bits:
  841. # First we try to extract a potential kwarg from the bit
  842. kwarg = token_kwargs([bit], parser)
  843. if kwarg:
  844. # The kwarg was successfully extracted
  845. param, value = list(six.iteritems(kwarg))[0]
  846. if param not in params and varkw is None:
  847. # An unexpected keyword argument was supplied
  848. raise TemplateSyntaxError(
  849. "'%s' received unexpected keyword argument '%s'" %
  850. (name, param))
  851. elif param in kwargs:
  852. # The keyword argument has already been supplied once
  853. raise TemplateSyntaxError(
  854. "'%s' received multiple values for keyword argument '%s'" %
  855. (name, param))
  856. else:
  857. # All good, record the keyword argument
  858. kwargs[str(param)] = value
  859. if param in unhandled_params:
  860. # If using the keyword syntax for a positional arg, then
  861. # consume it.
  862. unhandled_params.remove(param)
  863. else:
  864. if kwargs:
  865. raise TemplateSyntaxError(
  866. "'%s' received some positional argument(s) after some "
  867. "keyword argument(s)" % name)
  868. else:
  869. # Record the positional argument
  870. args.append(parser.compile_filter(bit))
  871. try:
  872. # Consume from the list of expected positional arguments
  873. unhandled_params.pop(0)
  874. except IndexError:
  875. if varargs is None:
  876. raise TemplateSyntaxError(
  877. "'%s' received too many positional arguments" %
  878. name)
  879. if defaults is not None:
  880. # Consider the last n params handled, where n is the
  881. # number of defaults.
  882. unhandled_params = unhandled_params[:-len(defaults)]
  883. if unhandled_params:
  884. # Some positional arguments were not supplied
  885. raise TemplateSyntaxError(
  886. "'%s' did not receive value(s) for the argument(s): %s" %
  887. (name, ", ".join("'%s'" % p for p in unhandled_params)))
  888. return args, kwargs
  889. def generic_tag_compiler(parser, token, params, varargs, varkw, defaults,
  890. name, takes_context, node_class):
  891. """
  892. Returns a template.Node subclass.
  893. """
  894. bits = token.split_contents()[1:]
  895. args, kwargs = parse_bits(parser, bits, params, varargs, varkw,
  896. defaults, takes_context, name)
  897. return node_class(takes_context, args, kwargs)
  898. class TagHelperNode(Node):
  899. """
  900. Base class for tag helper nodes such as SimpleNode, InclusionNode and
  901. AssignmentNode. Manages the positional and keyword arguments to be passed
  902. to the decorated function.
  903. """
  904. def __init__(self, takes_context, args, kwargs):
  905. self.takes_context = takes_context
  906. self.args = args
  907. self.kwargs = kwargs
  908. def get_resolved_arguments(self, context):
  909. resolved_args = [var.resolve(context) for var in self.args]
  910. if self.takes_context:
  911. resolved_args = [context] + resolved_args
  912. resolved_kwargs = dict((k, v.resolve(context)) for k, v in self.kwargs.items())
  913. return resolved_args, resolved_kwargs
  914. class Library(object):
  915. def __init__(self):
  916. self.filters = {}
  917. self.tags = {}
  918. def tag(self, name=None, compile_function=None):
  919. if name is None and compile_function is None:
  920. # @register.tag()
  921. return self.tag_function
  922. elif name is not None and compile_function is None:
  923. if callable(name):
  924. # @register.tag
  925. return self.tag_function(name)
  926. else:
  927. # @register.tag('somename') or @register.tag(name='somename')
  928. def dec(func):
  929. return self.tag(name, func)
  930. return dec
  931. elif name is not None and compile_function is not None:
  932. # register.tag('somename', somefunc)
  933. self.tags[name] = compile_function
  934. return compile_function
  935. else:
  936. raise InvalidTemplateLibrary("Unsupported arguments to "
  937. "Library.tag: (%r, %r)", (name, compile_function))
  938. def tag_function(self, func):
  939. self.tags[getattr(func, "_decorated_function", func).__name__] = func
  940. return func
  941. def filter(self, name=None, filter_func=None, **flags):
  942. if name is None and filter_func is None:
  943. # @register.filter()
  944. def dec(func):
  945. return self.filter_function(func, **flags)
  946. return dec
  947. elif name is not None and filter_func is None:
  948. if callable(name):
  949. # @register.filter
  950. return self.filter_function(name, **flags)
  951. else:
  952. # @register.filter('somename') or @register.filter(name='somename')
  953. def dec(func):
  954. return self.filter(name, func, **flags)
  955. return dec
  956. elif name is not None and filter_func is not None:
  957. # register.filter('somename', somefunc)
  958. self.filters[name] = filter_func
  959. for attr in ('expects_localtime', 'is_safe', 'needs_autoescape'):
  960. if attr in flags:
  961. value = flags[attr]
  962. # set the flag on the filter for FilterExpression.resolve
  963. setattr(filter_func, attr, value)
  964. # set the flag on the innermost decorated function
  965. # for decorators that need it e.g. stringfilter
  966. if hasattr(filter_func, "_decorated_function"):
  967. setattr(filter_func._decorated_function, attr, value)
  968. filter_func._filter_name = name
  969. return filter_func
  970. else:
  971. raise InvalidTemplateLibrary("Unsupported arguments to "
  972. "Library.filter: (%r, %r)", (name, filter_func))
  973. def filter_function(self, func, **flags):
  974. name = getattr(func, "_decorated_function", func).__name__
  975. return self.filter(name, func, **flags)
  976. def simple_tag(self, func=None, takes_context=None, name=None):
  977. def dec(func):
  978. params, varargs, varkw, defaults = getargspec(func)
  979. class SimpleNode(TagHelperNode):
  980. def render(self, context):
  981. resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
  982. return func(*resolved_args, **resolved_kwargs)
  983. function_name = (name or
  984. getattr(func, '_decorated_function', func).__name__)
  985. compile_func = partial(generic_tag_compiler,
  986. params=params, varargs=varargs, varkw=varkw,
  987. defaults=defaults, name=function_name,
  988. takes_context=takes_context, node_class=SimpleNode)
  989. compile_func.__doc__ = func.__doc__
  990. self.tag(function_name, compile_func)
  991. return func
  992. if func is None:
  993. # @register.simple_tag(...)
  994. return dec
  995. elif callable(func):
  996. # @register.simple_tag
  997. return dec(func)
  998. else:
  999. raise TemplateSyntaxError("Invalid arguments provided to simple_tag")
  1000. def assignment_tag(self, func=None, takes_context=None, name=None):
  1001. def dec(func):
  1002. params, varargs, varkw, defaults = getargspec(func)
  1003. class AssignmentNode(TagHelperNode):
  1004. def __init__(self, takes_context, args, kwargs, target_var):
  1005. super(AssignmentNode, self).__init__(takes_context, args, kwargs)
  1006. self.target_var = target_var
  1007. def render(self, context):
  1008. resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
  1009. context[self.target_var] = func(*resolved_args, **resolved_kwargs)
  1010. return ''
  1011. function_name = (name or
  1012. getattr(func, '_decorated_function', func).__name__)
  1013. def compile_func(parser, token):
  1014. bits = token.split_contents()[1:]
  1015. if len(bits) < 2 or bits[-2] != 'as':
  1016. raise TemplateSyntaxError(
  1017. "'%s' tag takes at least 2 arguments and the "
  1018. "second last argument must be 'as'" % function_name)
  1019. target_var = bits[-1]
  1020. bits = bits[:-2]
  1021. args, kwargs = parse_bits(parser, bits, params,
  1022. varargs, varkw, defaults, takes_context, function_name)
  1023. return AssignmentNode(takes_context, args, kwargs, target_var)
  1024. compile_func.__doc__ = func.__doc__
  1025. self.tag(function_name, compile_func)
  1026. return func
  1027. if func is None:
  1028. # @register.assignment_tag(...)
  1029. return dec
  1030. elif callable(func):
  1031. # @register.assignment_tag
  1032. return dec(func)
  1033. else:
  1034. raise TemplateSyntaxError("Invalid arguments provided to assignment_tag")
  1035. def inclusion_tag(self, file_name, context_class=Context, takes_context=False, name=None):
  1036. def dec(func):
  1037. params, varargs, varkw, defaults = getargspec(func)
  1038. class InclusionNode(TagHelperNode):
  1039. def render(self, context):
  1040. resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
  1041. _dict = func(*resolved_args, **resolved_kwargs)
  1042. if not getattr(self, 'nodelist', False):
  1043. from django.template.loader import get_template, select_template
  1044. if isinstance(file_name, Template):
  1045. t = file_name
  1046. elif not isinstance(file_name, six.string_types) and is_iterable(file_name):
  1047. t = select_template(file_name)
  1048. else:
  1049. t = get_template(file_name)
  1050. self.nodelist = t.nodelist
  1051. new_context = context_class(_dict, **{
  1052. 'autoescape': context.autoescape,
  1053. 'current_app': context.current_app,
  1054. 'use_l10n': context.use_l10n,
  1055. 'use_tz': context.use_tz,
  1056. })
  1057. # Copy across the CSRF token, if present, because
  1058. # inclusion tags are often used for forms, and we need
  1059. # instructions for using CSRF protection to be as simple
  1060. # as possible.
  1061. csrf_token = context.get('csrf_token', None)
  1062. if csrf_token is not None:
  1063. new_context['csrf_token'] = csrf_token
  1064. return self.nodelist.render(new_context)
  1065. function_name = (name or
  1066. getattr(func, '_decorated_function', func).__name__)
  1067. compile_func = partial(generic_tag_compiler,
  1068. params=params, varargs=varargs, varkw=varkw,
  1069. defaults=defaults, name=function_name,
  1070. takes_context=takes_context, node_class=InclusionNode)
  1071. compile_func.__doc__ = func.__doc__
  1072. self.tag(function_name, compile_func)
  1073. return func
  1074. return dec
  1075. def is_library_missing(name):
  1076. """Check if library that failed to load cannot be found under any
  1077. templatetags directory or does exist but fails to import.
  1078. Non-existing condition is checked recursively for each subpackage in cases
  1079. like <appdir>/templatetags/subpackage/package/module.py.
  1080. """
  1081. # Don't bother to check if '.' is in name since any name will be prefixed
  1082. # with some template root.
  1083. path, module = name.rsplit('.', 1)
  1084. try:
  1085. package = import_module(path)
  1086. return not module_has_submodule(package, module)
  1087. except ImportError:
  1088. return is_library_missing(path)
  1089. def import_library(taglib_module):
  1090. """
  1091. Load a template tag library module.
  1092. Verifies that the library contains a 'register' attribute, and
  1093. returns that attribute as the representation of the library
  1094. """
  1095. try:
  1096. mod = import_module(taglib_module)
  1097. except ImportError as e:
  1098. # If the ImportError is because the taglib submodule does not exist,
  1099. # that's not an error that should be raised. If the submodule exists
  1100. # and raised an ImportError on the attempt to load it, that we want
  1101. # to raise.
  1102. if is_library_missing(taglib_module):
  1103. return None
  1104. else:
  1105. raise InvalidTemplateLibrary("ImportError raised loading %s: %s" %
  1106. (taglib_module, e))
  1107. try:
  1108. return mod.register
  1109. except AttributeError:
  1110. raise InvalidTemplateLibrary("Template library %s does not have "
  1111. "a variable named 'register'" %
  1112. taglib_module)
  1113. templatetags_modules = []
  1114. def get_templatetags_modules():
  1115. """
  1116. Return the list of all available template tag modules.
  1117. Caches the result for faster access.
  1118. """
  1119. global templatetags_modules
  1120. if not templatetags_modules:
  1121. _templatetags_modules = []
  1122. # Populate list once per process. Mutate the local list first, and
  1123. # then assign it to the global name to ensure there are no cases where
  1124. # two threads try to populate it simultaneously.
  1125. templatetags_modules_candidates = ['django.templatetags']
  1126. templatetags_modules_candidates += ['%s.templatetags' % app_config.name
  1127. for app_config in apps.get_app_configs()]
  1128. for templatetag_module in templatetags_modules_candidates:
  1129. try:
  1130. import_module(templatetag_module)
  1131. _templatetags_modules.append(templatetag_module)
  1132. except ImportError:
  1133. continue
  1134. templatetags_modules = _templatetags_modules
  1135. return templatetags_modules
  1136. def get_library(library_name):
  1137. """
  1138. Load the template library module with the given name.
  1139. If library is not already loaded loop over all templatetags modules
  1140. to locate it.
  1141. {% load somelib %} and {% load someotherlib %} loops twice.
  1142. Subsequent loads eg. {% load somelib %} in the same process will grab
  1143. the cached module from libraries.
  1144. """
  1145. lib = libraries.get(library_name, None)
  1146. if not lib:
  1147. templatetags_modules = get_templatetags_modules()
  1148. tried_modules = []
  1149. for module in templatetags_modules:
  1150. taglib_module = '%s.%s' % (module, library_name)
  1151. tried_modules.append(taglib_module)
  1152. lib = import_library(taglib_module)
  1153. if lib:
  1154. libraries[library_name] = lib
  1155. break
  1156. if not lib:
  1157. raise InvalidTemplateLibrary("Template library %s not found, "
  1158. "tried %s" %
  1159. (library_name,
  1160. ','.join(tried_modules)))
  1161. return lib
  1162. def add_to_builtins(module):
  1163. builtins.append(import_library(module))
  1164. add_to_builtins('django.template.defaulttags')
  1165. add_to_builtins('django.template.defaultfilters')
  1166. add_to_builtins('django.template.loader_tags')