cc6b31391b505611671416cc281e255200f63e6f
[philo.git] / templatetags / containers.py
1 from django import template
2 from django.conf import settings
3 from django.utils.safestring import SafeUnicode, mark_safe
4 from django.core.exceptions import ObjectDoesNotExist
5 from django.contrib.contenttypes.models import ContentType
6
7
8 register = template.Library()
9
10
11 class ContainerNode(template.Node):
12         def __init__(self, name, references=None, as_var=None):
13                 self.name = name
14                 self.as_var = as_var
15                 self.references = references
16         def render(self, context):
17                 content = settings.TEMPLATE_STRING_IF_INVALID
18                 if 'page' in context:
19                         page = context['page']
20                         if self.references:
21                                 try:
22                                         contentreference = page.contentreferences.get(name__exact=self.name, content_type=self.references)
23                                         content = contentreference.content
24                                 except ObjectDoesNotExist:
25                                         pass
26                         else:
27                                 try:
28                                         contentlet = page.contentlets.get(name__exact=self.name)
29                                         if contentlet.dynamic:
30                                                 try:
31                                                         content = mark_safe(template.Template(contentlet.content, name=contentlet.name).render(context))
32                                                 except template.TemplateSyntaxError, error:
33                                                         if settings.DEBUG:
34                                                                 content = ('[Error parsing contentlet \'%s\': %s]' % self.name, error)
35                                         else:
36                                                 content = contentlet.content
37                                 except ObjectDoesNotExist:
38                                         pass
39                 if content and self.as_var:
40                         context[self.as_var] = content
41                         return ''
42                 return content
43
44
45 def do_container(parser, token):
46         """
47         {% container <name> [[references <type>] as <variable>] %}
48         """
49         params = token.split_contents()
50         if len(params) >= 2:
51                 name = params[1].strip('"')
52                 references = None
53                 as_var = None
54                 if len(params) > 2:
55                         remaining_tokens = params[2:]
56                         while remaining_tokens:
57                                 option_token = remaining_tokens.pop(0)
58                                 if option_token == 'references':
59                                         try:
60                                                 app_label, model = remaining_tokens.pop(0).strip('"').split('.')
61                                                 references = ContentType.objects.get(app_label=app_label, model=model)
62                                         except IndexError:
63                                                 raise template.TemplateSyntaxError('"container" template tag option "references" requires an argument specifying a content type')
64                                         except ValueError:
65                                                 raise template.TemplateSyntaxError('"container" template tag option "references" requires an argument of the form app_label.model (see django.contrib.contenttypes)')
66                                         except ObjectDoesNotExist:
67                                                 raise template.TemplateSyntaxError('"container" template tag option "references" requires an argument of the form app_label.model which refers to an installed content type (see django.contrib.contenttypes)')
68                                 elif option_token == 'as':
69                                         try:
70                                                 as_var = remaining_tokens.pop(0)
71                                         except IndexError:
72                                                 raise template.TemplateSyntaxError('"container" template tag option "as" requires an argument specifying a variable name')
73                         if references and not as_var:
74                                 raise template.TemplateSyntaxError('"container" template tags using "references" option require additional use of the "as" option specifying a variable name')
75                 return ContainerNode(name, references, as_var)
76         else: # error
77                 raise template.TemplateSyntaxError('"container" template tag provided without arguments (at least one required)')
78 register.tag('container', do_container)