# HG changeset patch # User Aurelien Campeas # Date 1267531241 -3600 # Node ID f9a176ebe090e9713a39cf442da72a8d2f27d207 # Parent fee30ae3bc08ef8db100fde9af9d8d4f4e99e992 [book/controllers] add some content (overview, api super sketch) for the cubicweb controllers diff -r fee30ae3bc08 -r f9a176ebe090 doc/book/en/development/devweb/controllers.rst --- 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. + + + diff -r fee30ae3bc08 -r f9a176ebe090 web/controller.py --- 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 diff -r fee30ae3bc08 -r f9a176ebe090 web/views/basecontrollers.py --- 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)