--- a/view.py Fri Feb 12 15:18:00 2010 +0100
+++ b/view.py Wed Mar 24 10:23:31 2010 +0100
@@ -21,7 +21,6 @@
from cubicweb import NotAnEntity
from cubicweb.selectors import yes, non_final_entity, nonempty_rset, none_rset
-from cubicweb.selectors import require_group_compat, accepts_compat
from cubicweb.appobject import AppObject
from cubicweb.utils import UStringIO, HTMLStream
from cubicweb.schema import display_name
@@ -92,12 +91,11 @@
* the `category` attribute may be used in the interface to regroup related
objects together
- At instantiation time, the standard `req`, `rset`, and `cursor`
- attributes are added and the `w` attribute will be set at rendering
- time to a write function to use.
+ At instantiation time, the standard `_cw`, and `cw_rset` attributes are
+ added and the `w` attribute will be set at rendering time to a write
+ function to use.
"""
__registry__ = 'views'
- registered = require_group_compat(AppObject.registered)
templatable = True
# content_type = 'application/xhtml+xml' # text/xhtml'
@@ -119,12 +117,12 @@
return True
def __init__(self, req=None, rset=None, **kwargs):
- super(View, self).__init__(req, rset, **kwargs)
+ super(View, self).__init__(req, rset=rset, **kwargs)
self.w = None
@property
def content_type(self):
- return self.req.html_content_type()
+ return self._cw.html_content_type()
def set_stream(self, w=None):
if self.w is not None:
@@ -167,7 +165,20 @@
if stream is not None:
return self._stream.getvalue()
- dispatch = deprecated('.dispatch is deprecated, use .render')(render)
+ def tal_render(self, template, variables):
+ """render a precompiled page template with variables in the given
+ dictionary as context
+ """
+ from cubicweb.ext.tal import CubicWebContext
+ context = CubicWebContext()
+ context.update({'self': self, 'rset': self.cw_rset, '_' : self._cw._,
+ 'req': self._cw, 'user': self._cw.user})
+ context.update(variables)
+ output = UStringIO()
+ template.expand(context, output)
+ return output.getvalue()
+
+ dispatch = deprecated('[3.4] .dispatch is deprecated, use .render')(render)
# should default .call() method add a <div classs="section"> around each
# rset item
@@ -180,15 +191,15 @@
Views applicable on None result sets have to override this method
"""
- rset = self.rset
+ rset = self.cw_rset
if rset is None:
- raise NotImplementedError, self
+ raise NotImplementedError, (self, "an rset is required")
wrap = self.templatable and len(rset) > 1 and self.add_div_section
# XXX propagate self.extra_kwars?
for i in xrange(len(rset)):
if wrap:
self.w(u'<div class="section">')
- self.wview(self.id, rset, row=i, **kwargs)
+ self.wview(self.__regid__, rset, row=i, **kwargs)
if wrap:
self.w(u"</div>")
@@ -206,23 +217,23 @@
return True
def is_primary(self):
- return self.extra_kwargs.get('is_primary', self.id == 'primary')
+ return self.cw_extra_kwargs.get('is_primary', self.__regid__ == 'primary')
def url(self):
"""return the url associated with this view. Should not be
necessary for non linkable views, but a default implementation
is provided anyway.
"""
- rset = self.rset
+ rset = self.cw_rset
if rset is None:
- return self.build_url('view', vid=self.id)
+ return self._cw.build_url('view', vid=self.__regid__)
coltypes = rset.column_types(0)
if len(coltypes) == 1:
etype = iter(coltypes).next()
- if not self.schema.eschema(etype).final:
+ if not self._cw.vreg.schema.eschema(etype).final:
if len(rset) == 1:
entity = rset.get_entity(0, 0)
- return entity.absolute_url(vid=self.id)
+ return entity.absolute_url(vid=self.__regid__)
# don't want to generate /<etype> url if there is some restriction
# on something else than the entity type
restr = rset.syntax_tree().children[0].where
@@ -232,25 +243,25 @@
norestriction = (isinstance(restr, nodes.Relation) and
restr.is_types_restriction())
if norestriction:
- return self.build_url(etype.lower(), vid=self.id)
- return self.build_url('view', rql=rset.printable_rql(), vid=self.id)
+ return self._cw.build_url(etype.lower(), vid=self.__regid__)
+ return self._cw.build_url('view', rql=rset.printable_rql(), vid=self.__regid__)
def set_request_content_type(self):
"""set the content type returned by this view"""
- self.req.set_content_type(self.content_type)
+ self._cw.set_content_type(self.content_type)
# view utilities ##########################################################
def wview(self, __vid, rset=None, __fallback_vid=None, **kwargs):
"""shortcut to self.view method automatically passing self.w as argument
"""
- self.view(__vid, rset, __fallback_vid, w=self.w, **kwargs)
+ self._cw.view(__vid, rset, __fallback_vid, w=self.w, **kwargs)
# XXX Template bw compat
- template = deprecated('.template is deprecated, use .view')(wview)
+ template = deprecated('[3.4] .template is deprecated, use .view')(wview)
def whead(self, data):
- self.req.html_headers.write(data)
+ self._cw.html_headers.write(data)
def wdata(self, data):
"""simple helper that escapes `data` and writes into `self.w`"""
@@ -268,34 +279,34 @@
"""returns a title according to the result set - used for the
title in the HTML header
"""
- vtitle = self.req.form.get('vtitle')
+ vtitle = self._cw.form.get('vtitle')
if vtitle:
- return self.req._(vtitle)
+ return self._cw._(vtitle)
# class defined title will only be used if the resulting title doesn't
# seem clear enough
vtitle = getattr(self, 'title', None) or u''
if vtitle:
- vtitle = self.req._(vtitle)
- rset = self.rset
+ vtitle = self._cw._(vtitle)
+ rset = self.cw_rset
if rset and rset.rowcount:
if rset.rowcount == 1:
try:
- entity = self.complete_entity(0)
+ entity = rset.complete_entity(0, 0)
# use long_title to get context information if any
clabel = entity.dc_long_title()
except NotAnEntity:
- clabel = display_name(self.req, rset.description[0][0])
+ clabel = display_name(self._cw, rset.description[0][0])
clabel = u'%s (%s)' % (clabel, vtitle)
else :
etypes = rset.column_types(0)
if len(etypes) == 1:
etype = iter(etypes).next()
- clabel = display_name(self.req, etype, 'plural')
+ clabel = display_name(self._cw, etype, 'plural')
else :
clabel = u'#[*] (%s)' % vtitle
else:
clabel = vtitle
- return u'%s (%s)' % (clabel, self.req.property_value('ui.site-title'))
+ return u'%s (%s)' % (clabel, self._cw.property_value('ui.site-title'))
def output_url_builder( self, name, url, args ):
self.w(u'<script language="JavaScript"><!--\n' \
@@ -310,8 +321,8 @@
self.w('}\n-->\n</script>\n')
def create_url(self, etype, **kwargs):
- """return the url of the entity creation form for a given entity type"""
- return self.req.build_url('add/%s' % etype, **kwargs)
+ """ return the url of the entity creation form for a given entity type"""
+ return self._cw.build_url('add/%s' % etype, **kwargs)
def field(self, label, value, row=True, show_label=True, w=None, tr=True, table=False):
"""read-only field"""
@@ -323,7 +334,7 @@
w(u'<div class="entityfield">')
if show_label and label:
if tr:
- label = display_name(self.req, label)
+ label = display_name(self._cw, label)
if table:
w(u'<th>%s</th>' % label)
else:
@@ -343,8 +354,6 @@
class EntityView(View):
"""base class for views applying on an entity (i.e. uniform result set)"""
__select__ = non_final_entity()
- registered = accepts_compat(View.registered)
-
category = 'entityview'
@@ -353,7 +362,6 @@
displayed (so they can always be displayed !)
"""
__select__ = none_rset()
- registered = require_group_compat(View.registered)
category = 'startupview'
@@ -375,7 +383,7 @@
default_rql = None
def __init__(self, req, rset=None, **kwargs):
- super(EntityStartupView, self).__init__(req, rset, **kwargs)
+ super(EntityStartupView, self).__init__(req, rset=rset, **kwargs)
if rset is None:
# this instance is not in the "entityview" category
self.category = 'startupview'
@@ -388,11 +396,11 @@
"""override call to execute rql returned by the .startup_rql method if
necessary
"""
- if self.rset is None:
- self.rset = self.req.execute(self.startup_rql())
- rset = self.rset
+ rset = self.cw_rset
+ if rset is None:
+ rset = self.cw_rset = self._cw.execute(self.startup_rql())
for i in xrange(len(rset)):
- self.wview(self.id, rset, row=i, **kwargs)
+ self.wview(self.__regid__, rset, row=i, **kwargs)
class AnyRsetView(View):
@@ -403,18 +411,18 @@
def columns_labels(self, mainindex=0, tr=True):
if tr:
- translate = lambda val, req=self.req: display_name(req, val)
+ translate = lambda val, req=self._cw: display_name(req, val)
else:
translate = lambda val: val
# XXX [0] because of missing Union support
- rqlstdescr = self.rset.syntax_tree().get_description(mainindex,
- translate)[0]
+ rqlstdescr = self.cw_rset.syntax_tree().get_description(mainindex,
+ translate)[0]
labels = []
for colindex, label in enumerate(rqlstdescr):
# compute column header
if label == 'Any': # find a better label
label = ','.join(translate(et)
- for et in self.rset.column_types(colindex))
+ for et in self.cw_rset.column_types(colindex))
labels.append(label)
return labels
@@ -426,11 +434,10 @@
There is usually at least a regular main template and a simple fallback
one to display error if the first one failed
"""
- registered = require_group_compat(View.registered)
@property
def doctype(self):
- if self.req.xhtml_browser():
+ if self._cw.xhtml_browser():
return STRICT_DOCTYPE
return STRICT_DOCTYPE_NOEXT
@@ -441,7 +448,7 @@
if self.binary:
self._stream = stream = StringIO()
else:
- self._stream = stream = HTMLStream(self.req)
+ self._stream = stream = HTMLStream(self._cw)
w = stream.write
else:
stream = None
@@ -466,16 +473,16 @@
"""register the given user callback and return an url to call it ready to be
inserted in html
"""
- self.req.add_js('cubicweb.ajax.js')
+ self._cw.add_js('cubicweb.ajax.js')
if nonify:
_cb = cb
def cb(*args):
_cb(*args)
- cbname = self.req.register_onetime_callback(cb, *args)
+ cbname = self._cw.register_onetime_callback(cb, *args)
return self.build_js(cbname, xml_escape(msg or ''))
def build_update_js_call(self, cbname, msg):
- rql = self.rset.printable_rql()
+ rql = self.cw_rset.printable_rql()
return "javascript:userCallbackThenUpdateUI('%s', '%s', %s, %s, '%s', '%s')" % (
cbname, self.id, dumps(rql), dumps(msg),
self.__registry__, self.div_id())
@@ -493,12 +500,12 @@
"""base class for components"""
__registry__ = 'components'
__select__ = yes()
- property_defs = {}
# XXX huummm, much probably useless
htmlclass = 'mainRelated'
def div_class(self):
- return '%s %s' % (self.htmlclass, self.id)
- # XXX a generic '%s%s' % (self.id, self.__registry__.capitalize()) would probably be nicer
+ return '%s %s' % (self.htmlclass, self.__regid__)
+
+ # XXX a generic '%s%s' % (self.__regid__, self.__registry__.capitalize()) would probably be nicer
def div_id(self):
- return '%sComponent' % self.id
+ return '%sComponent' % self.__regid__