comparison roundup/cgi/templating.py @ 4740:fe9568a6cbd6

Untangle template selection logic from template loading functionality.
author anatoly techtonik <techtonik@gmail.com>
date Tue, 15 Jan 2013 00:10:01 +0300
parents dfa516063571
children 9cc6d463cfbe
comparison
equal deleted inserted replaced
4739:94be76e04140 4740:fe9568a6cbd6
75 def __str__(self): 75 def __str__(self):
76 return self._('You are not allowed to %(action)s ' 76 return self._('You are not allowed to %(action)s '
77 'items of class %(class)s') % { 77 'items of class %(class)s') % {
78 'action': self.action, 'class': self.klass} 78 'action': self.action, 'class': self.klass}
79 79
80 def find_template(dir, name, view):
81 """ Find a template in the nominated dir
82 """
83 # find the source
84 if view:
85 filename = '%s.%s'%(name, view)
86 else:
87 filename = name
88
89 # try old-style
90 src = os.path.join(dir, filename)
91 if os.path.exists(src):
92 return (src, filename)
93
94 # try with a .html or .xml extension (new-style)
95 for extension in '.html', '.xml':
96 f = filename + extension
97 src = os.path.join(dir, f)
98 if os.path.exists(src):
99 return (src, f)
100
101 # no view == no generic template is possible
102 if not view:
103 raise NoTemplate, 'Template file "%s" doesn\'t exist'%name
104
105 # try _generic template for the view
106 generic = '_generic.%s'%view
107 src = os.path.join(dir, generic)
108 if os.path.exists(src):
109 return (src, generic)
110
111 # finally, try _generic.html
112 generic = generic + '.html'
113 src = os.path.join(dir, generic)
114 if os.path.exists(src):
115 return (src, generic)
116
117 raise NoTemplate('No template file exists for templating "%s" '
118 'with template "%s" (neither "%s" nor "%s")'%(name, view,
119 filename, generic))
120
121 class LoaderBase: 80 class LoaderBase:
122 """Base for engine-specific template Loader class.""" 81 """ Base for engine-specific template Loader class."""
123 def precompileTemplates(self): 82 def precompileTemplates(self):
124 """ Go through a directory and precompile all the templates therein 83 """ Go through a directory and precompile all the templates therein
125 """ 84 """
126 for filename in os.listdir(self.dir): 85 for filename in os.listdir(self.dir):
127 # skip subdirs 86 # skip subdirs
135 else: 94 else:
136 continue 95 continue
137 96
138 # remove extension 97 # remove extension
139 filename = filename[:-len(extension)] 98 filename = filename[:-len(extension)]
140 99 self.load(filename)
141 # load the template 100
142 if '.' in filename: 101 def load(self, tplname):
143 name, view = filename.split('.', 1)
144 self.load(name, view)
145 else:
146 self.load(filename, None)
147
148 def load(self, name, view=None):
149 """ Load template and return template object with render() method. 102 """ Load template and return template object with render() method.
150 103
151 "name" and "view" are used to select the template, which in 104 "tplname" is a template name. For filesystem loaders it is a
152 most cases will be "name.view". If "view" is None, then a 105 filename without extensions, typically in the "classname.view"
153 template called "name" will be selected. 106 format.
154 107 """
155 If the file "name.view" doesn't exist, we look for 108 raise NotImplementedError
156 "_generic.view" as a fallback. 109
157 """ 110 def check(self, name):
158 # [ ] document default 'home' template and other special pages 111 """ Check if template with the given name exists. Return None or
112 a tuple (src, filename) that can be reused in load() method.
113 """
159 raise NotImplementedError 114 raise NotImplementedError
160 115
161 def __getitem__(self, name): 116 def __getitem__(self, name):
162 """Special method to access templates by loader['name']""" 117 """Special method to access templates by loader['name']"""
163 view = None
164 if '.' in name:
165 name, view = name.split('.', 1)
166 try: 118 try:
167 return self.load(name, view) 119 return self.load(name)
168 except NoTemplate, message: 120 except NoTemplate, message:
169 raise KeyError, message 121 raise KeyError, message
122
170 123
171 def get_loader(dir, engine_name): 124 def get_loader(dir, engine_name):
172 if engine_name == 'chameleon': 125 if engine_name == 'chameleon':
173 import engine_chameleon as engine 126 import engine_chameleon as engine
174 else: 127 else:
698 req = HTMLRequest(self._client) 651 req = HTMLRequest(self._client)
699 req.classname = self.classname 652 req.classname = self.classname
700 req.update(kwargs) 653 req.update(kwargs)
701 654
702 # new template, using the specified classname and request 655 # new template, using the specified classname and request
703 pt = self._client.instance.templates.load(self.classname, name) 656 # [ ] this code is too similar to client.renderContext()
657 tplname = self._client.selectTemplate(self.classname, name)
658 pt = self._client.instance.templates.load(tplname)
704 659
705 # use our fabricated request 660 # use our fabricated request
706 args = { 661 args = {
707 'ok_message': self._client.ok_message, 662 'ok_message': self._client.ok_message,
708 'error_message': self._client.error_message 663 'error_message': self._client.error_message
843 # make link if hrefable 798 # make link if hrefable
844 if (self._props.has_key(prop_n) and 799 if (self._props.has_key(prop_n) and
845 isinstance(self._props[prop_n], hyperdb.Link)): 800 isinstance(self._props[prop_n], hyperdb.Link)):
846 classname = self._props[prop_n].classname 801 classname = self._props[prop_n].classname
847 try: 802 try:
848 template = find_template(self._db.config.TEMPLATES, 803 template = self._client.selectTemplate(classname, 'item')
849 classname, 'item') 804 if template.startswith('_generic.'):
850 if template[1].startswith('_generic'):
851 raise NoTemplate, 'not really...' 805 raise NoTemplate, 'not really...'
852 except NoTemplate: 806 except NoTemplate:
853 pass 807 pass
854 else: 808 else:
855 id = self._klass.get(self._nodeid, prop_n, None) 809 id = self._klass.get(self._nodeid, prop_n, None)
915 comments[classname] = self._( 869 comments[classname] = self._(
916 "The linked class %(classname)s no longer exists" 870 "The linked class %(classname)s no longer exists"
917 ) % locals() 871 ) % locals()
918 labelprop = linkcl.labelprop(1) 872 labelprop = linkcl.labelprop(1)
919 try: 873 try:
920 template = find_template(self._db.config.TEMPLATES, 874 template = self._client.selectTemplate(classname,
921 classname, 'item') 875 'item')
922 if template[1].startswith('_generic'): 876 if template.startswith('_generic.'):
923 raise NoTemplate, 'not really...' 877 raise NoTemplate, 'not really...'
924 hrefable = 1 878 hrefable = 1
925 except NoTemplate: 879 except NoTemplate:
926 hrefable = 0 880 hrefable = 0
927 881
1085 name = self._klass.get(self._nodeid, 'name') 1039 name = self._klass.get(self._nodeid, 'name')
1086 req.updateFromURL(self._klass.get(self._nodeid, 'url') + 1040 req.updateFromURL(self._klass.get(self._nodeid, 'url') +
1087 '&@queryname=%s'%urllib.quote(name)) 1041 '&@queryname=%s'%urllib.quote(name))
1088 1042
1089 # new template, using the specified classname and request 1043 # new template, using the specified classname and request
1090 pt = self._client.instance.templates.load(req.classname, 'search') 1044 # [ ] the custom logic for search page doesn't belong to
1045 # generic templating module (techtonik)
1046 tplname = self._client.selectTemplate(req.classname, 'search')
1047 pt = self._client.instance.templates.load(tplname)
1091 # The context for a search page should be the class, not any 1048 # The context for a search page should be the class, not any
1092 # node. 1049 # node.
1093 self._client.nodeid = None 1050 self._client.nodeid = None
1094 1051
1095 # use our fabricated request 1052 # use our fabricated request

Roundup Issue Tracker: http://roundup-tracker.org/