[book/controllers] add some content (overview, api super sketch) for the cubicweb controllers
--- a/doc/book/en/development/devweb/controllers.rst Tue Mar 02 12:04:33 2010 +0100
+++ b/doc/book/en/development/devweb/controllers.rst Tue Mar 02 13:00:41 2010 +0100
@@ -1,4 +1,79 @@
Controllers
-----------
-XXX the view controller, other controllers
\ No newline at end of file
+Overview
+++++++++
+
+Controllers are responsible for taking action upon user requests
+(loosely following the terminology of the MVC meta pattern).
+
+The following controllers are provided out-of-the box in CubicWeb. We
+list them by category.
+
+Browsing:
+
+* the View controller (web/views/basecontrollers.py) is associated
+ with most browsing actions within a CubicWeb application: it always
+ instantiates a `main template` and lets the ResultSet/Views dispatch
+ system build up the whole content; it handles ObjectNotFound and
+ NoSelectableObject errors that may bubble up to its entry point, in
+ an end-user-friendly way (but other programming errors will slip
+ through)
+
+* the JSon controller (web/views/basecontrollers.py) provides services
+ for Ajax calls, typically using JSON as a serialization format for
+ input, and sometimes using either JSON or XML for output;
+
+* the Login/Logout controllers (web/views/basecontrollers.py) make
+ effective user login or logout requests
+
+Edition:
+
+* the Edit controller (web/views/editcontroller.py) handles CRUD
+ operations in response to a form being submitted; it works in close
+ association with the Forms, to which it delegates some of the work
+
+* the Form validator controller (web/views/basecontrollers.py)
+ provides form validation from Ajax context, using the Edit
+ controller, to implement the classic form handling loop (user edits,
+ hits 'submit/apply', validation occurs server-side by way of the
+ Form validator controller, and the UI is decorated with failure
+ information, either global or per-field , until it is valid)
+
+Other:
+
+* the SendMail controller (web/views/basecontrollers.py) is reponsible
+ for outgoing email notifications
+
+* the MailBugReport controller (web/views/basecontrollers.py) allows
+ to quickly have a `repotbug` feature in one's application
+
+Registration
+++++++++++++
+
+All controllers (should) live in the 'controllers' namespace within
+the global registry.
+
+API
++++
+
+Most API details should be resolved by source code inspection, as the
+various controllers have differing goals.
+
+`web/controller.py` contains the top-level abstract Controller class and
+its (NotImplemented) entry point `publish(rset=None)` method.
+
+A handful of helpers are also provided there:
+
+* process_rql builds a result set from an rql query typically issued
+ from the browser (and available through _cw.form['rql'])
+
+* validate_cache will force cache validation handling with respect to
+ the HTTP Cache directives (that were typically originally issued
+ from a previous server -> client response); concrete Controller
+ implementations dealing with HTTP (thus, for instance, not the
+ SendMail controller) may very well call this in their publication
+ process.
+
+
+
--- a/web/controller.py Tue Mar 02 12:04:33 2010 +0100
+++ b/web/controller.py Tue Mar 02 13:00:41 2010 +0100
@@ -61,12 +61,10 @@
self._edited_entity = None
def publish(self, rset=None):
- """publish the current request, with an option input rql string
- (already processed if necessary)
- """
+ """publish the current request, with an optional input rset"""
raise NotImplementedError
- # generic methods useful for concret implementations ######################
+ # generic methods useful for concrete implementations ######################
def process_rql(self, rql):
"""execute rql if specified"""
@@ -102,6 +100,7 @@
if not self._edited_entity:
self._edited_entity = entity
+ # XXX move to EditController (only customer)
def delete_entities(self, eidtypes):
"""delete entities from the repository"""
redirect_info = set()
@@ -125,6 +124,7 @@
view.set_http_cache_headers()
self._cw.validate_cache()
+ # XXX is that used AT ALL ?
def reset(self):
"""reset form parameters and redirect to a view determinated by given
parameters
@@ -141,6 +141,7 @@
self._return_to_original_view(newparams)
+ # XXX is that used AT ALL ?
def _return_to_original_view(self, newparams):
"""validate-button case"""
# transforms __redirect[*] parameters into regular form parameters
@@ -173,7 +174,7 @@
url = append_url_params(url, self._cw.form.get('__redirectparams'))
raise Redirect(url)
-
+ # XXX is that used AT ALL ?
def _return_to_edition_view(self, newparams):
"""apply-button case"""
form = self._cw.form
@@ -197,6 +198,7 @@
raise Redirect(self._cw.build_url(path, **newparams))
+ # XXX is that used AT ALL ?
def _return_to_lastpage(self, newparams):
"""cancel-button case: in this case we are always expecting to go back
where we came from, and this is not easy. Currently we suppose that
--- a/web/views/basecontrollers.py Tue Mar 02 12:04:33 2010 +0100
+++ b/web/views/basecontrollers.py Tue Mar 02 13:00:41 2010 +0100
@@ -375,12 +375,12 @@
rset = self._exec(rql)
else:
rset = None
- comp = self._cw.vreg[registry].select(compid, self._cw, rset=rset)
if extraargs is None:
extraargs = {}
else: # we receive unicode keys which is not supported by the **syntax
extraargs = dict((str(key), value)
for key, value in extraargs.items())
+ comp = self._cw.vreg[registry].select(compid, self._cw, rset=rset, **extraargs)
extraargs = extraargs or {}
return comp.render(**extraargs)