153 """render a precompiled page template with variables in the given |
153 """render a precompiled page template with variables in the given |
154 dictionary as context |
154 dictionary as context |
155 """ |
155 """ |
156 from cubicweb.ext.tal import CubicWebContext |
156 from cubicweb.ext.tal import CubicWebContext |
157 context = CubicWebContext() |
157 context = CubicWebContext() |
158 context.update({'self': self, 'rset': self.rset, '_' : self.req._, |
158 context.update({'self': self, 'rset': self.cw_rset, '_' : self._cw._, |
159 'req': self.req, 'user': self.req.user}) |
159 'req': self._cw, 'user': self._cw.user}) |
160 context.update(variables) |
160 context.update(variables) |
161 output = UStringIO() |
161 output = UStringIO() |
162 template.expand(context, output) |
162 template.expand(context, output) |
163 return output.getvalue() |
163 return output.getvalue() |
164 |
164 |
173 other rows of the result set and call the same view on the |
173 other rows of the result set and call the same view on the |
174 particular row |
174 particular row |
175 |
175 |
176 Views applicable on None result sets have to override this method |
176 Views applicable on None result sets have to override this method |
177 """ |
177 """ |
178 rset = self.rset |
178 rset = self.cw_rset |
179 if rset is None: |
179 if rset is None: |
180 raise NotImplementedError, self |
180 raise NotImplementedError, self |
181 wrap = self.templatable and len(rset) > 1 and self.add_div_section |
181 wrap = self.templatable and len(rset) > 1 and self.add_div_section |
182 for i in xrange(len(rset)): |
182 for i in xrange(len(rset)): |
183 if wrap: |
183 if wrap: |
184 self.w(u'<div class="section">') |
184 self.w(u'<div class="section">') |
185 self.wview(self.id, rset, row=i, **kwargs) |
185 self.wview(self.__regid__, rset, row=i, **kwargs) |
186 if wrap: |
186 if wrap: |
187 self.w(u"</div>") |
187 self.w(u"</div>") |
188 |
188 |
189 def cell_call(self, row, col, **kwargs): |
189 def cell_call(self, row, col, **kwargs): |
190 """the view is called for a particular result set cell""" |
190 """the view is called for a particular result set cell""" |
198 if not getattr(self, 'title', None): |
198 if not getattr(self, 'title', None): |
199 return False |
199 return False |
200 return True |
200 return True |
201 |
201 |
202 def is_primary(self): |
202 def is_primary(self): |
203 return self.id == 'primary' |
203 return self.__regid__ == 'primary' |
204 |
204 |
205 def url(self): |
205 def url(self): |
206 """return the url associated with this view. Should not be |
206 """return the url associated with this view. Should not be |
207 necessary for non linkable views, but a default implementation |
207 necessary for non linkable views, but a default implementation |
208 is provided anyway. |
208 is provided anyway. |
209 """ |
209 """ |
210 rset = self.rset |
210 rset = self.cw_rset |
211 if rset is None: |
211 if rset is None: |
212 return self.build_url('view', vid=self.id) |
212 return self._cw.build_url('view', vid=self.__regid__) |
213 coltypes = rset.column_types(0) |
213 coltypes = rset.column_types(0) |
214 if len(coltypes) == 1: |
214 if len(coltypes) == 1: |
215 etype = iter(coltypes).next() |
215 etype = iter(coltypes).next() |
216 if not self.schema.eschema(etype).is_final(): |
216 if not self._cw.schema.eschema(etype).is_final(): |
217 if len(rset) == 1: |
217 if len(rset) == 1: |
218 entity = rset.get_entity(0, 0) |
218 entity = rset.get_entity(0, 0) |
219 return entity.absolute_url(vid=self.id) |
219 return entity.absolute_url(vid=self.__regid__) |
220 # don't want to generate /<etype> url if there is some restriction |
220 # don't want to generate /<etype> url if there is some restriction |
221 # on something else than the entity type |
221 # on something else than the entity type |
222 restr = rset.syntax_tree().children[0].where |
222 restr = rset.syntax_tree().children[0].where |
223 # XXX norestriction is not correct here. For instance, in cases like |
223 # XXX norestriction is not correct here. For instance, in cases like |
224 # "Any P,N WHERE P is Project, P name N" norestriction should equal |
224 # "Any P,N WHERE P is Project, P name N" norestriction should equal |
225 # True |
225 # True |
226 norestriction = (isinstance(restr, nodes.Relation) and |
226 norestriction = (isinstance(restr, nodes.Relation) and |
227 restr.is_types_restriction()) |
227 restr.is_types_restriction()) |
228 if norestriction: |
228 if norestriction: |
229 return self.build_url(etype.lower(), vid=self.id) |
229 return self._cw.build_url(etype.lower(), vid=self.__regid__) |
230 return self.build_url('view', rql=rset.printable_rql(), vid=self.id) |
230 return self._cw.build_url('view', rql=rset.printable_rql(), vid=self.__regid__) |
231 |
231 |
232 def set_request_content_type(self): |
232 def set_request_content_type(self): |
233 """set the content type returned by this view""" |
233 """set the content type returned by this view""" |
234 self.req.set_content_type(self.content_type) |
234 self._cw.set_content_type(self.content_type) |
235 |
235 |
236 # view utilities ########################################################## |
236 # view utilities ########################################################## |
237 |
237 |
238 def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs): |
238 def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs): |
239 """shortcut to self.view method automatically passing self.w as argument |
239 """shortcut to self.view method automatically passing self.w as argument |
240 """ |
240 """ |
241 self.view(__vid, rset, __fallback_vid, w=self.w, **kwargs) |
241 self._cw.view(__vid, rset, __fallback_vid, w=self.w, **kwargs) |
242 |
242 |
243 # XXX Template bw compat |
243 # XXX Template bw compat |
244 template = deprecated('[3.4] .template is deprecated, use .view')(wview) |
244 template = deprecated('[3.4] .template is deprecated, use .view')(wview) |
245 |
245 |
246 def whead(self, data): |
246 def whead(self, data): |
247 self.req.html_headers.write(data) |
247 self._cw.html_headers.write(data) |
248 |
248 |
249 def wdata(self, data): |
249 def wdata(self, data): |
250 """simple helper that escapes `data` and writes into `self.w`""" |
250 """simple helper that escapes `data` and writes into `self.w`""" |
251 self.w(xml_escape(data)) |
251 self.w(xml_escape(data)) |
252 |
252 |
260 |
260 |
261 def page_title(self): |
261 def page_title(self): |
262 """returns a title according to the result set - used for the |
262 """returns a title according to the result set - used for the |
263 title in the HTML header |
263 title in the HTML header |
264 """ |
264 """ |
265 vtitle = self.req.form.get('vtitle') |
265 vtitle = self._cw.form.get('vtitle') |
266 if vtitle: |
266 if vtitle: |
267 return self.req._(vtitle) |
267 return self._cw._(vtitle) |
268 # class defined title will only be used if the resulting title doesn't |
268 # class defined title will only be used if the resulting title doesn't |
269 # seem clear enough |
269 # seem clear enough |
270 vtitle = getattr(self, 'title', None) or u'' |
270 vtitle = getattr(self, 'title', None) or u'' |
271 if vtitle: |
271 if vtitle: |
272 vtitle = self.req._(vtitle) |
272 vtitle = self._cw._(vtitle) |
273 rset = self.rset |
273 rset = self.cw_rset |
274 if rset and rset.rowcount: |
274 if rset and rset.rowcount: |
275 if rset.rowcount == 1: |
275 if rset.rowcount == 1: |
276 try: |
276 try: |
277 entity = self.complete_entity(0) |
277 entity = rset.complete_entity(0, 0) |
278 # use long_title to get context information if any |
278 # use long_title to get context information if any |
279 clabel = entity.dc_long_title() |
279 clabel = entity.dc_long_title() |
280 except NotAnEntity: |
280 except NotAnEntity: |
281 clabel = display_name(self.req, rset.description[0][0]) |
281 clabel = display_name(self._cw, rset.description[0][0]) |
282 clabel = u'%s (%s)' % (clabel, vtitle) |
282 clabel = u'%s (%s)' % (clabel, vtitle) |
283 else : |
283 else : |
284 etypes = rset.column_types(0) |
284 etypes = rset.column_types(0) |
285 if len(etypes) == 1: |
285 if len(etypes) == 1: |
286 etype = iter(etypes).next() |
286 etype = iter(etypes).next() |
287 clabel = display_name(self.req, etype, 'plural') |
287 clabel = display_name(self._cw, etype, 'plural') |
288 else : |
288 else : |
289 clabel = u'#[*] (%s)' % vtitle |
289 clabel = u'#[*] (%s)' % vtitle |
290 else: |
290 else: |
291 clabel = vtitle |
291 clabel = vtitle |
292 return u'%s (%s)' % (clabel, self.req.property_value('ui.site-title')) |
292 return u'%s (%s)' % (clabel, self._cw.property_value('ui.site-title')) |
293 |
293 |
294 def output_url_builder( self, name, url, args ): |
294 def output_url_builder( self, name, url, args ): |
295 self.w(u'<script language="JavaScript"><!--\n' \ |
295 self.w(u'<script language="JavaScript"><!--\n' \ |
296 u'function %s( %s ) {\n' % (name, ','.join(args) ) ) |
296 u'function %s( %s ) {\n' % (name, ','.join(args) ) ) |
297 url_parts = url.split("%s") |
297 url_parts = url.split("%s") |
303 self.w('\n document.window.href=url;\n') |
303 self.w('\n document.window.href=url;\n') |
304 self.w('}\n-->\n</script>\n') |
304 self.w('}\n-->\n</script>\n') |
305 |
305 |
306 def create_url(self, etype, **kwargs): |
306 def create_url(self, etype, **kwargs): |
307 """ return the url of the entity creation form for a given entity type""" |
307 """ return the url of the entity creation form for a given entity type""" |
308 return self.req.build_url('add/%s'%etype, **kwargs) |
308 return self._cw.build_url('add/%s'%etype, **kwargs) |
309 |
309 |
310 def field(self, label, value, row=True, show_label=True, w=None, tr=True): |
310 def field(self, label, value, row=True, show_label=True, w=None, tr=True): |
311 """ read-only field """ |
311 """ read-only field """ |
312 if w is None: |
312 if w is None: |
313 w = self.w |
313 w = self.w |
314 if row: |
314 if row: |
315 w(u'<div class="row">') |
315 w(u'<div class="row">') |
316 if show_label and label: |
316 if show_label and label: |
317 if tr: |
317 if tr: |
318 label = display_name(self.req, label) |
318 label = display_name(self._cw, label) |
319 w(u'<span class="label">%s</span>' % label) |
319 w(u'<span class="label">%s</span>' % label) |
320 w(u'<div class="field">%s</div>' % value) |
320 w(u'<div class="field">%s</div>' % value) |
321 if row: |
321 if row: |
322 w(u'</div>') |
322 w(u'</div>') |
323 |
323 |
368 |
368 |
369 def call(self, **kwargs): |
369 def call(self, **kwargs): |
370 """override call to execute rql returned by the .startup_rql method if |
370 """override call to execute rql returned by the .startup_rql method if |
371 necessary |
371 necessary |
372 """ |
372 """ |
373 if self.rset is None: |
373 rset = self.cw_rset |
374 self.rset = self.req.execute(self.startup_rql()) |
374 if rset is None: |
375 rset = self.rset |
375 rset = self.cw_rset = self._cw.execute(self.startup_rql()) |
376 for i in xrange(len(rset)): |
376 for i in xrange(len(rset)): |
377 self.wview(self.id, rset, row=i, **kwargs) |
377 self.wview(self.__regid__, rset, row=i, **kwargs) |
378 |
378 |
379 |
379 |
380 class AnyRsetView(View): |
380 class AnyRsetView(View): |
381 """base class for views applying on any non empty result sets""" |
381 """base class for views applying on any non empty result sets""" |
382 __select__ = nonempty_rset() |
382 __select__ = nonempty_rset() |
383 |
383 |
384 category = 'anyrsetview' |
384 category = 'anyrsetview' |
385 |
385 |
386 def columns_labels(self, mainindex=0, tr=True): |
386 def columns_labels(self, mainindex=0, tr=True): |
387 if tr: |
387 if tr: |
388 translate = lambda val, req=self.req: display_name(req, val) |
388 translate = lambda val, req=self._cw: display_name(req, val) |
389 else: |
389 else: |
390 translate = lambda val: val |
390 translate = lambda val: val |
391 # XXX [0] because of missing Union support |
391 # XXX [0] because of missing Union support |
392 rqlstdescr = self.rset.syntax_tree().get_description(mainindex, |
392 rqlstdescr = self.cw_rset.syntax_tree().get_description(mainindex, |
393 translate)[0] |
393 translate)[0] |
394 labels = [] |
394 labels = [] |
395 for colindex, label in enumerate(rqlstdescr): |
395 for colindex, label in enumerate(rqlstdescr): |
396 # compute column header |
396 # compute column header |
397 if label == 'Any': # find a better label |
397 if label == 'Any': # find a better label |
398 label = ','.join(translate(et) |
398 label = ','.join(translate(et) |
399 for et in self.rset.column_types(colindex)) |
399 for et in self.cw_rset.column_types(colindex)) |
400 labels.append(label) |
400 labels.append(label) |
401 return labels |
401 return labels |
402 |
402 |
403 |
403 |
404 # concrete template base classes ############################################## |
404 # concrete template base classes ############################################## |
445 |
445 |
446 def user_callback(self, cb, args, msg=None, nonify=False): |
446 def user_callback(self, cb, args, msg=None, nonify=False): |
447 """register the given user callback and return an url to call it ready to be |
447 """register the given user callback and return an url to call it ready to be |
448 inserted in html |
448 inserted in html |
449 """ |
449 """ |
450 self.req.add_js('cubicweb.ajax.js') |
450 self._cw.add_js('cubicweb.ajax.js') |
451 if nonify: |
451 if nonify: |
452 _cb = cb |
452 _cb = cb |
453 def cb(*args): |
453 def cb(*args): |
454 _cb(*args) |
454 _cb(*args) |
455 cbname = self.req.register_onetime_callback(cb, *args) |
455 cbname = self._cw.register_onetime_callback(cb, *args) |
456 return self.build_js(cbname, xml_escape(msg or '')) |
456 return self.build_js(cbname, xml_escape(msg or '')) |
457 |
457 |
458 def build_update_js_call(self, cbname, msg): |
458 def build_update_js_call(self, cbname, msg): |
459 rql = xml_escape(self.rset.printable_rql()) |
459 rql = xml_escape(self.cw_rset.printable_rql()) |
460 return "javascript:userCallbackThenUpdateUI('%s', '%s', '%s', '%s', '%s', '%s')" % ( |
460 return "javascript:userCallbackThenUpdateUI('%s', '%s', '%s', '%s', '%s', '%s')" % ( |
461 cbname, self.id, rql, msg, self.__registry__, self.div_id()) |
461 cbname, self.__regid__, rql, msg, self.__registry__, self.div_id()) |
462 |
462 |
463 def build_reload_js_call(self, cbname, msg): |
463 def build_reload_js_call(self, cbname, msg): |
464 return "javascript:userCallbackThenReloadPage('%s', '%s')" % (cbname, msg) |
464 return "javascript:userCallbackThenReloadPage('%s', '%s')" % (cbname, msg) |
465 |
465 |
466 build_js = build_update_js_call # expect updatable component by default |
466 build_js = build_update_js_call # expect updatable component by default |