62 indexurl = self.build_url('view', vid='index', __message=msg) |
62 indexurl = self.build_url('view', vid='index', __message=msg) |
63 w(u'<p><a href="%s">%s</a><p>' % ( |
63 w(u'<p><a href="%s">%s</a><p>' % ( |
64 html_escape(indexurl), |
64 html_escape(indexurl), |
65 self.req._('go back to the index page'))) |
65 self.req._('go back to the index page'))) |
66 |
66 |
|
67 @objectify_selector |
|
68 def templatable_view(cls, req, rset, *args, **kwargs): |
|
69 view = kwargs.pop('view', None) |
|
70 if view is None: |
|
71 return 1 |
|
72 if view.binary: |
|
73 return 0 |
|
74 if req.form.has_key('__notemplate'): |
|
75 return 0 |
|
76 return view.templatable |
|
77 |
|
78 @objectify_selector |
|
79 def non_templatable_view(cls, req, rset, *args, **kwargs): |
|
80 return not templatable_view()(cls, req, rset, *args, **kwargs) |
|
81 |
|
82 |
|
83 class NonTemplatableViewTemplate(MainTemplate): |
|
84 """main template for any non templatable views (xml, binaries, etc.)""" |
|
85 id = 'main-template' |
|
86 __select__ = non_templatable_view() |
|
87 |
|
88 def call(self, view): |
|
89 view.set_request_content_type() |
|
90 self.set_stream(templatable=False) |
|
91 # have to replace our unicode stream using view's binary stream |
|
92 view.dispatch() |
|
93 assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream |
|
94 self._stream = view._stream |
|
95 |
67 |
96 |
68 class TheMainTemplate(MainTemplate): |
97 class TheMainTemplate(MainTemplate): |
69 """default main template : |
98 """default main template : |
70 |
99 |
71 - call header / footer templates |
100 - call header / footer templates |
72 - build result set |
|
73 - guess and call an appropriate view through the view manager |
|
74 """ |
101 """ |
75 id = 'main' |
102 id = 'main-template' |
76 |
103 __select__ = templatable_view() |
77 def _select_view_and_rset(self): |
104 |
78 req = self.req |
105 def call(self, view): |
79 if self.rset is None and not hasattr(req, '_rql_processed'): |
106 self.set_request_content_type() |
80 req._rql_processed = True |
107 self.template_header(self.content_type, view) |
81 rset = self.process_rql(req.form.get('rql')) |
108 w = self.w |
82 else: |
109 w(u'<div id="pageContent">\n') |
83 rset = self.rset |
110 vtitle = self.req.form.get('vtitle') |
84 # handle special "method" param when necessary |
111 if vtitle: |
85 # XXX this should probably not be in the template (controller ?), however: |
112 w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle)) |
86 # * we need to have the displayed rset |
113 # display entity type restriction component |
87 # * we don't want to handle it in each view |
114 etypefilter = self.vreg.select_component('etypenavigation', |
88 if rset and rset.rowcount == 1 and '__method' in req.form: |
115 self.req, self.rset) |
89 entity = rset.get_entity(0, 0) |
116 if etypefilter and etypefilter.propval('visible'): |
90 try: |
117 etypefilter.dispatch(w=w) |
91 method = getattr(entity, req.form.pop('__method')) |
118 self.nav_html = UStringIO() |
92 method() |
119 self.pagination(self.req, self.rset, self.nav_html.write, |
93 except Exception, ex: |
120 not (view and view.need_navigation)) |
94 self.exception('while handling __method') |
121 w(_(self.nav_html.getvalue())) |
95 req.set_message(req._("error while handling __method: %s") % req._(ex)) |
122 w(u'<div id="contentmain">\n') |
96 vid = req.form.get('vid') or vid_from_rset(req, rset, self.schema) |
123 view.dispatch(w=w) |
97 try: |
124 w(u'</div>\n') # close id=contentmain |
98 view = self.vreg.select_view(vid, req, rset) |
125 w(_(self.nav_html.getvalue())) |
99 except ObjectNotFound: |
126 w(u'</div>\n') # closes id=pageContent |
100 self.warning("the view %s could not be found", vid) |
127 self.template_footer(view) |
101 req.set_message(req._("The view %s could not be found") % vid) |
|
102 vid = vid_from_rset(req, rset, self.schema) |
|
103 view = self.vreg.select_view(vid, req, rset) |
|
104 except NoSelectableObject: |
|
105 if rset: |
|
106 req.set_message(req._("The view %s can not be applied to this query") % vid) |
|
107 else: |
|
108 req.set_message(req._("You have no access to this view or it's not applyable to current data")) |
|
109 self.warning("the view %s can not be applied to this query", vid) |
|
110 vid = vid_from_rset(req, rset, self.schema) |
|
111 view = self.vreg.select_view(vid, req, rset) |
|
112 return view, rset |
|
113 |
|
114 def call(self): |
|
115 view, rset = self._select_view_and_rset() |
|
116 req = self.req |
|
117 # update breadcrumps **before** validating cache, unless the view |
|
118 # specifies explicitly it should not be added to breadcrumb or the |
|
119 # view is a binary view |
|
120 if view.add_to_breadcrumbs and not view.binary: |
|
121 req.update_breadcrumbs() |
|
122 view.set_http_cache_headers() |
|
123 req.validate_cache() |
|
124 with_templates = self.with_templates(view) |
|
125 if with_templates: |
|
126 self.set_request_content_type() |
|
127 content_type = self.content_type |
|
128 self.template_header(content_type, view) |
|
129 else: |
|
130 view.set_request_content_type() |
|
131 self.set_stream(templatable=False) |
|
132 self.wview('page-content', view=view, rset=rset) |
|
133 if with_templates: |
|
134 self.template_footer(view) |
|
135 |
|
136 def with_templates(self, view): |
|
137 return (not view.binary and view.templatable and |
|
138 not self.req.form.has_key('__notemplate')) |
|
139 |
|
140 def process_rql(self, rql): |
|
141 """execute rql if specified""" |
|
142 if rql: |
|
143 self.ensure_ro_rql(rql) |
|
144 if not isinstance(rql, unicode): |
|
145 rql = unicode(rql, self.req.encoding) |
|
146 pp = self.vreg.select_component('magicsearch', self.req) |
|
147 self.rset = pp.process_query(rql, self.req) |
|
148 return self.rset |
|
149 return None |
|
150 |
128 |
151 def template_header(self, content_type, view=None, page_title='', additional_headers=()): |
129 def template_header(self, content_type, view=None, page_title='', additional_headers=()): |
152 page_title = page_title or view.page_title() |
130 page_title = page_title or view.page_title() |
153 additional_headers = additional_headers or view.html_headers() |
131 additional_headers = additional_headers or view.html_headers() |
154 self.template_html_header(content_type, page_title, additional_headers) |
132 self.template_html_header(content_type, page_title, additional_headers) |
202 """by default, display informal messages in content header""" |
180 """by default, display informal messages in content header""" |
203 self.wview('contentheader', rset=self.rset, view=view) |
181 self.wview('contentheader', rset=self.rset, view=view) |
204 |
182 |
205 def content_footer(self, view=None): |
183 def content_footer(self, view=None): |
206 self.wview('contentfooter', rset=self.rset, view=view) |
184 self.wview('contentfooter', rset=self.rset, view=view) |
207 |
|
208 |
|
209 class PageContentTemplate(TheMainTemplate): |
|
210 id = 'page-content' |
|
211 |
|
212 def call(self, view=None, rset=None): |
|
213 if view is None: |
|
214 view, rset = self._select_view_and_rset() |
|
215 with_templates = self.with_templates(view) |
|
216 w = self.w |
|
217 if with_templates: |
|
218 w(u'<div id="pageContent">\n') |
|
219 vtitle = self.req.form.get('vtitle') |
|
220 if vtitle: |
|
221 w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle)) |
|
222 # display entity type restriction component |
|
223 etypefilter = self.vreg.select_component('etypenavigation', |
|
224 self.req, self.rset) |
|
225 if etypefilter and etypefilter.propval('visible'): |
|
226 etypefilter.dispatch(w=w) |
|
227 self.nav_html = UStringIO() |
|
228 self.pagination(self.req, self.rset, self.nav_html.write, |
|
229 not (view and view.need_navigation)) |
|
230 w(_(self.nav_html.getvalue())) |
|
231 w(u'<div id="contentmain">\n') |
|
232 else: |
|
233 self.set_stream(templatable=False) |
|
234 if view.binary: |
|
235 # have to replace our unicode stream using view's binary stream |
|
236 view.dispatch() |
|
237 assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream |
|
238 self._stream = view._stream |
|
239 else: |
|
240 view.dispatch(w=w) |
|
241 if with_templates: |
|
242 w(u'</div>\n') # close id=contentmain |
|
243 w(_(self.nav_html.getvalue())) |
|
244 w(u'</div>\n') # closes id=pageContent |
|
245 |
185 |
246 |
186 |
247 class ErrorTemplate(TheMainTemplate): |
187 class ErrorTemplate(TheMainTemplate): |
248 """fallback template if an internal error occured during displaying the |
188 """fallback template if an internal error occured during displaying the |
249 main template. This template may be called for authentication error, |
189 main template. This template may be called for authentication error, |