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