Merge branch 'docs' into release
[philo.git] / philo / 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         
17         def render(self, context):
18                 content = settings.TEMPLATE_STRING_IF_INVALID
19                 if 'page' in context:
20                         container_content = self.get_container_content(context)
21                 else:
22                         container_content = None
23                 
24                 if self.as_var:
25                         context[self.as_var] = container_content
26                         return ''
27                 
28                 if not container_content:
29                         return ''
30                 
31                 return container_content
32         
33         def get_container_content(self, context):
34                 page = context['page']
35                 if self.references:
36                         # Then it's a content reference.
37                         try:
38                                 contentreference = page.contentreferences.get(name__exact=self.name, content_type=self.references)
39                                 content = contentreference.content
40                         except ObjectDoesNotExist:
41                                 content = ''
42                 else:
43                         # Otherwise it's a contentlet.
44                         try:
45                                 contentlet = page.contentlets.get(name__exact=self.name)
46                                 if '{%' in contentlet.content or '{{' in contentlet.content:
47                                         try:
48                                                 content = template.Template(contentlet.content, name=contentlet.name).render(context)
49                                         except template.TemplateSyntaxError, error:
50                                                 if settings.DEBUG:
51                                                         content = ('[Error parsing contentlet \'%s\': %s]' % (self.name, error))
52                                                 else:
53                                                         content = settings.TEMPLATE_STRING_IF_INVALID
54                                 else:
55                                         content = contentlet.content
56                         except ObjectDoesNotExist:
57                                 content = settings.TEMPLATE_STRING_IF_INVALID
58                         content = mark_safe(content)
59                 return content
60
61
62 def do_container(parser, token):
63         """
64         {% container <name> [[references <type>] as <variable>] %}
65         """
66         params = token.split_contents()
67         if len(params) >= 2:
68                 tag = params[0]
69                 name = params[1].strip('"')
70                 references = None
71                 as_var = None
72                 if len(params) > 2:
73                         remaining_tokens = params[2:]
74                         while remaining_tokens:
75                                 option_token = remaining_tokens.pop(0)
76                                 if option_token == 'references':
77                                         try:
78                                                 app_label, model = remaining_tokens.pop(0).strip('"').split('.')
79                                                 references = ContentType.objects.get(app_label=app_label, model=model)
80                                         except IndexError:
81                                                 raise template.TemplateSyntaxError('"%s" template tag option "references" requires an argument specifying a content type' % tag)
82                                         except ValueError:
83                                                 raise template.TemplateSyntaxError('"%s" template tag option "references" requires an argument of the form app_label.model (see django.contrib.contenttypes)' % tag)
84                                         except ObjectDoesNotExist:
85                                                 raise template.TemplateSyntaxError('"%s" template tag option "references" requires an argument of the form app_label.model which refers to an installed content type (see django.contrib.contenttypes)' % tag)
86                                 elif option_token == 'as':
87                                         try:
88                                                 as_var = remaining_tokens.pop(0)
89                                         except IndexError:
90                                                 raise template.TemplateSyntaxError('"%s" template tag option "as" requires an argument specifying a variable name' % tag)
91                         if references and not as_var:
92                                 raise template.TemplateSyntaxError('"%s" template tags using "references" option require additional use of the "as" option specifying a variable name' % tag)
93                 return ContainerNode(name, references, as_var)
94                 
95         else: # error
96                 raise template.TemplateSyntaxError('"%s" template tag provided without arguments (at least one required)' % tag)
97
98
99 register.tag('container', do_container)