doc/book/en/development/devweb/views.rst
branchstable
changeset 5262 ebd90d2a5639
parent 5222 ed6905d98a5e
--- a/doc/book/en/development/devweb/views.rst	Wed Apr 14 18:10:09 2010 +0200
+++ b/doc/book/en/development/devweb/views.rst	Wed Apr 14 18:10:47 2010 +0200
@@ -8,45 +8,50 @@
 the development of a web application and how it has been implemented
 in *CubicWeb*.
 
-We'll start with a description of the interface providing you with a basic
-understanding of the available classes and methods, then detail the view
-selection principle which makes *CubicWeb* web interface very flexible.
+We'll start with a description of the interface providing you with a
+basic understanding of the available classes and methods, then detail
+the view selection principle.
 
-A `View` is an object applied to another object such as an entity.
+A `View` is an object responsible for the rendering of data from the
+model into an end-user consummable form. They typically churn out an
+XHTML stream, but there are views concerned with email other non-html
+outputs.
 
 Basic class for views
 ~~~~~~~~~~~~~~~~~~~~~
 
 Class `View` (`cubicweb.view`)
-`````````````````````````````````````
+```````````````````````````````
 
 This class is an abstraction of a view class, used as a base class for every
 renderable object such as views, templates, graphic components, etc.
 
-A `View` is instantiated to render a result set or part of a result set. `View`
-subclasses may be parametrized using the following class attributes:
+A `View` is instantiated to render a result set or part of a result
+set. `View` subclasses may be parametrized using the following class
+attributes:
 
 * `templatable` indicates if the view may be embedded in a main
-  template or if it has to be rendered standalone (i.e. XML views must
-  not be embedded in the main template for HTML pages)
+  template or if it has to be rendered standalone (i.e. pure XML views
+  must not be embedded in the main template of HTML pages)
 
 * if the view is not templatable, it should set the `content_type`
-  class attribute to the correct MIME type (text/xhtml by default)
+  class attribute to the correct MIME type (text/xhtml being the
+  default)
 
 * the `category` attribute may be used in the interface to regroup
-  related objects together
+  related view kinds together
 
-A view writes to its output stream thanks to its attribute `w` (an
-`UStreamIO`, except for binary views).
+A view writes to its output stream thanks to its attribute `w` (the
+append method of an `UStreamIO`, except for binary views).
 
 At instantiation time, the standard `_cw` and `cw_rset` attributes are
 added and the `w` attribute will be set at rendering time.
 
-The basic interface for views is as follows (remember that the result set has a
-tabular structure with rows and columns, hence cells):
+The basic interface for views is as follows (remember that the result
+set has a tabular structure with rows and columns, hence cells):
 
 * `render(**context)`, render the view by calling `call` or
-  `cell_call` depending on the given parameters
+  `cell_call` depending on the context
 
 * `call(**kwargs)`, call the view for a complete result set or null
   (the default implementation calls `cell_call()` on each cell of the
@@ -93,7 +98,7 @@
         cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
 
 
-- Using custom selector
+- Using a custom selector
 
 .. sourcecode:: python
 
@@ -107,148 +112,6 @@
 
 
 
-Example of view customization and creation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We'll show you now an example of a ``primary`` view and how to customize it.
-
-If you want to change the way a ``BlogEntry`` is displayed, just override
-the method ``cell_call()`` of the view ``primary`` in ``BlogDemo/views.py``:
-
-.. sourcecode:: python
-
-  from cubicweb.selectors import implements
-  from cubicweb.web.views.primary improt Primaryview
-
-  class BlogEntryPrimaryView(PrimaryView):
-    __select__ = PrimaryView.__select__ & implements('BlogEntry')
-
-      def render_entity_attributes(self, entity):
-          self.w(u'<p>published on %s</p>' %
-                 entity.publish_date.strftime('%Y-%m-%d'))
-          super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
-
-The above source code defines a new primary view for
-``BlogEntry``. The `id` class attribute is not repeated there since it
-is inherited through the `primary.PrimaryView` class.
-
-The selector for this view chains the selector of the inherited class
-with its own specific criterion.
-
-The view method ``self.w()`` is used to output data. Here `lines
-08-09` output HTML for the publication date of the entry.
-
-.. image:: ../../images/lax-book.09-new-view-blogentry.en.png
-   :alt: blog entries now look much nicer
-
-Let us now improve the primary view of a blog
-
-.. sourcecode:: python
-
- from logilab.mtconverter import xml_escape
- from cubicweb.selectors import implements, one_line_rset
- from cubicweb.web.views.primary import Primaryview
-
- class BlogPrimaryView(PrimaryView):
-     __regid__ = 'primary'
-     __select__ = PrimaryView.__select__ & implements('Blog')
-     rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'
-
-     def render_entity_relations(self, entity):
-         rset = self._cw.execute(self.rql, {'b' : entity.eid})
-         for entry in rset.entities():
-             self.w(u'<p>%s</p>' % entry.view('inblogcontext'))
-
- class BlogEntryInBlogView(EntityView):
-     __regid__ = 'inblogcontext'
-     __select__ = implements('BlogEntry')
-
-     def cell_call(self, row, col):
-         entity = self.cw_rset.get_entity(row, col)
-         self.w(u'<a href="%s" title="%s">%s</a>' %
-                entity.absolute_url(),
-                xml_escape(entity.content[:50]),
-                xml_escape(entity.description))
-
-This happens in two places. First we override the
-render_entity_relations method of a Blog's primary view. Here we want
-to display our blog entries in a custom way.
-
-At `line 10`, a simple request is made to build a result set with all
-the entities linked to the current ``Blog`` entity by the relationship
-``entry_of``. The part of the framework handling the request knows
-about the schema and infers that such entities have to be of the
-``BlogEntry`` kind and retrieves them (in the prescribed publish_date
-order).
-
-The request returns a selection of data called a result set. Result
-set objects have an .entities() method returning a generator on
-requested entities (going transparently through the `ORM` layer).
-
-At `line 13` the view 'inblogcontext' is applied to each blog entry to
-output HTML. (Note that the 'inblogcontext' view is not defined
-whatsoever in *CubicWeb*. You are absolutely free to define whole view
-families.) We juste arrange to wrap each blogentry output in a 'p'
-html element.
-
-Next, we define the 'inblogcontext' view. This is NOT a primary view,
-with its well-defined sections (title, metadata, attribtues,
-relations/boxes). All a basic view has to define is cell_call.
-
-Since views are applied to result sets which can be tables of data, we
-have to recover the entity from its (row,col)-coordinates (`line
-20`). Then we can spit some HTML.
-
-But careful: all strings manipulated in *CubicWeb* are actually
-unicode strings. While web browsers are usually tolerant to incoherent
-encodings they are being served, we should not abuse it. Hence we have
-to properly escape our data. The xml_escape() function has to be used
-to safely fill (X)HTML elements from Python unicode strings.
-
-
-**This is to be compared to interfaces and protocols in object-oriented
-languages. Applying a given view called 'a_view' to all the entities
-of a result set only requires to have for each entity of this result set,
-an available view called 'a_view' which accepts the entity.**
-
-**Instead of merely using type based dispatch, we do predicate dispatch
-which is quite more powerful.**
-
-Assuming we added entries to the blog titled `MyLife`, displaying it
-now allows to read its description and all its entries.
-
-.. image:: ../../images/lax-book.10-blog-with-two-entries.en.png
-   :alt: a blog and all its entries
-
-**Before we move forward, remember that the selection/view principle is
-at the core of *CubicWeb*. Everywhere in the engine, data is requested
-using the RQL language, then HTML/XML/text/PNG is output by applying a
-view to the result set returned by the query. That is where most of the
-flexibility comes from.**
-
-[WRITE ME]
-
-* implementing interfaces, calendar for blog entries
-* show that a calendar view can export data to ical
-
-We will implement the `cubicweb.interfaces.ICalendarable` interfaces on
-entities.BlogEntry and apply the OneMonthCalendar and iCalendar views
-to result sets like "Any E WHERE E is BlogEntry"
-
-* create view "blogentry table" with title, publish_date, category
-
-We will show that by default the view that displays
-"Any E,D,C WHERE E publish_date D, E category C" is the table view.
-Of course, the same can be obtained by calling
-self.wview('table',rset)
-
-* in view blog, select blogentries and apply view "blogentry table"
-* demo ajax by filtering blogentry table on category
-
-we did the same with 'primary', but with tables we can turn on filters
-and show that ajax comes for free.
-[FILLME]
-
 
 XML views, binaries views...
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -258,8 +121,9 @@
 by the main template (see above), you have to:
 
 * set the attribute `templatable` of the class to `False`
-* set, through the attribute `content_type` of the class, the MIME type generated
-  by the view to `application/octet-stream`
+* set, through the attribute `content_type` of the class, the MIME
+  type generated by the view to `application/octet-stream` or any
+  relevant and more specialised mime type
 
 For views dedicated to binary content creation (like dynamically generated
 images), we have to set the attribute `binary` of the class to `True` (which