[book/controllers] add some content (overview, api super sketch) for the cubicweb controllers stable
authorAurelien Campeas <aurelien.campeas@logilab.fr>
Tue, 02 Mar 2010 13:00:41 +0100
branchstable
changeset 4741 f9a176ebe090
parent 4740 fee30ae3bc08
child 4742 fac80328a6a3
child 4743 026a89520184
[book/controllers] add some content (overview, api super sketch) for the cubicweb controllers
doc/book/en/development/devweb/controllers.rst
web/controller.py
web/views/basecontrollers.py
--- 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)