doc/book/en/05-00-define-views.en.txt
changeset 145 d5acef862c58
parent 144 3159772915c4
parent 141 6d008838f2c9
child 146 f8035a67971a
equal deleted inserted replaced
144:3159772915c4 145:d5acef862c58
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 .. _DefinitionVues:
       
     4 
       
     5 Views definition
       
     6 ================
       
     7 
       
     8 Basic class for views
       
     9 ---------------------
       
    10 
       
    11 Class `View` (`cubicweb.common.view`)
       
    12 `````````````````````````````````````
       
    13 
       
    14 A view writes in its output exit thanks to its attribute `w` (`UStreamIO`).
       
    15 
       
    16 The basic interface for views is as follows:
       
    17 
       
    18 * `dispatch(**context)`, render the view by calling `call` or
       
    19   `cell_call` depending on the given parameters
       
    20 * `call(**kwargs)`, call the view for a complete result set or null
       
    21 * `cell_call(row, col, **kwargs)`, call the view for a given cell of a result set
       
    22 * `url()`, returns the URL enabling us to get the view with the current
       
    23   result set 
       
    24 * `view(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of identifier 
       
    25   `__vid` on the given result set. It is possible to give a view identifier
       
    26   of fallback that will be used if the view requested is not applicable to the
       
    27   result set
       
    28   
       
    29 * `wview(__vid, rset, __fallback_vid=None, **kwargs)`, similar to `view` except
       
    30   the flow is automatically passed in the parameters
       
    31   
       
    32 * `html_headers()`, returns a list of HTML headers to set by the main template
       
    33 
       
    34 * `page_title()`, returns the title to use in the HTML header `title`
       
    35 
       
    36 * `creator(eid)`, returns the eid and the login of the entity creator of the entity
       
    37   having the eid given in the parameter 
       
    38 
       
    39 Other basic classes:
       
    40 
       
    41 * `EntityView`, view applying to lines or cell containing an entity (e.g. an eid)
       
    42 * `StartupView`, start view that does not require a result set to apply to
       
    43 * `AnyRsetView`, view applied to any result set 
       
    44 
       
    45 
       
    46 The selection view principle
       
    47 ----------------------------
       
    48 
       
    49 A view includes :
       
    50 
       
    51 - an identifier (all objects in `LAX` are entered in a registry
       
    52   and this identifier will be used as a key)
       
    53   
       
    54 - a filter to select the resulsets it can be applied to
       
    55 
       
    56 
       
    57 For a given identifier, multiple views can be defined. `CubicWeb` uses
       
    58 a selector which computes scores so that it can identify and select the
       
    59 best view to apply in context. The selector library is in 
       
    60 ``cubicweb.common.selector`` and a library of the methods used to
       
    61 compute scores is in ``cubicweb.vregistry.vreq``.
       
    62 
       
    63 
       
    64 `CubicWeb` provides a lot of standard views, for a complete list, you
       
    65 will have to read the code in directory ``cubicweb/web/views/`` (XXX
       
    66 improve doc).
       
    67 
       
    68 For example, the view named ``primary`` is the one used to display
       
    69 a single entity.
       
    70 
       
    71 If you want to change the way a ``BlogEntry`` is displayed, just
       
    72 override the view ``primary`` in ``BlogDemo/views.py`` ::
       
    73 
       
    74   01. from ginco.web.views import baseviews
       
    75   02.
       
    76   03. class BlogEntryPrimaryView(baseviews.PrimaryView):
       
    77   04.
       
    78   05.     accepts = ('BlogEntry',)
       
    79   06.
       
    80   07.     def cell_call(self, row, col):
       
    81   08.         entity = self.entity(row, col)
       
    82   09.         self.w(u'<h1>%s</h1>' % entity.title)
       
    83   10.         self.w(u'<p>published on %s in category %s</p>' % \
       
    84   11.                (entity.publish_date.strftime('%Y-%m-%d'), entity.category))
       
    85   12.         self.w(u'<p>%s</p>' % entity.text)
       
    86 
       
    87 The above source code defines a new primary view (`line 03`) for
       
    88 ``BlogEntry`` (`line 05`). 
       
    89 
       
    90 Since views are applied to resultsets and resulsets can be tables of
       
    91 data, it is needed to recover the entity from its (row,col)
       
    92 coordinates (`line 08`). We will get to this in more detail later.
       
    93 
       
    94 The view has a ``self.w()`` method that is used to output data. Here `lines
       
    95 09-12` output HTML tags and values of the entity's attributes.
       
    96 
       
    97 When displaying same blog entry as before, you will notice that the
       
    98 page is now looking much nicer.
       
    99 
       
   100 .. image:: images/lax-book.09-new-view-blogentry.en.png
       
   101    :alt: blog entries now look much nicer
       
   102 
       
   103 Let us now improve the primary view of a blog ::
       
   104 
       
   105   01. class BlogPrimaryView(baseviews.PrimaryView):
       
   106   02. 
       
   107   03.     accepts = ('Blog',)
       
   108   04.
       
   109   05.     def cell_call(self, row, col):
       
   110   06.         entity = self.entity(row, col)
       
   111   07.         self.w(u'<h1>%s</h1>' % entity.title)
       
   112   08.         self.w(u'<p>%s</p>' % entity.description)
       
   113   09.         rset = self.req.execute('Any E WHERE E entry_of B, B eid "%s"' % entity.eid)
       
   114   10.         self.wview('primary', rset)
       
   115 
       
   116 In the above source code, `lines 01-08` are similar to the previous
       
   117 view we defined.
       
   118 
       
   119 At `line 09`, a simple request in made to build a resultset with all
       
   120 the entities linked to the current ``Blog`` entity by the relationship
       
   121 ``entry_of``. The part of the framework handling the request knows
       
   122 about the schema and infer that such entities have to be of the
       
   123 ``BlogEntry`` kind and retrieves them.
       
   124 
       
   125 The request returns a selection of data called a resultset. At 
       
   126 `line 10` the view 'primary' is applied to this resultset to output
       
   127 HTML. 
       
   128 
       
   129 **This is to be compared to interfaces and protocols in object-oriented
       
   130 languages. Applying a given view to all the entities of a resultset only
       
   131 requires the availability, for each entity of this resultset, of a
       
   132 view with that name that can accepts the entity.**
       
   133 
       
   134 Assuming we added entries to the blog titled `MyLife`, displaying it
       
   135 now allows to read its description and all its entries.
       
   136 
       
   137 .. image:: images/lax-book.10-blog-with-two-entries.en.png
       
   138    :alt: a blog and all its entries
       
   139 
       
   140 **Before we move forward, remember that the selection/view principle is
       
   141 at the core of `CubicWeb`. Everywhere in the engine, data is requested
       
   142 using the RQL language, then HTML/XML/text/PNG is output by applying a
       
   143 view to the resultset returned by the query. That is where most of the
       
   144 flexibility comes from.**
       
   145 
       
   146 [WRITE ME]
       
   147 
       
   148 * implementing interfaces, calendar for blog entries
       
   149 * show that a calendar view can export data to ical
       
   150 
       
   151 We will implement the cubicwweb.interfaces.ICalendarable interfaces on
       
   152 entities.BloEntry and apply the OneMonthCalendar and iCalendar views
       
   153 to resultsets like "Any E WHERE E is BlogEntry"
       
   154 
       
   155 * create view "blogentry table" with title, publish_date, category
       
   156 
       
   157 We will show that by default the view that displays 
       
   158 "Any E,D,C WHERE E publish_date D, E category C" is the table view.
       
   159 Of course, the same can be obtained by calling
       
   160 self.wview('table',rset)
       
   161 
       
   162 * in view blog, select blogentries and apply view "blogentry table"
       
   163 * demo ajax by filtering blogentry table on category
       
   164 
       
   165 we did the same with 'primary', but with tables we can turn on filters
       
   166 and show that ajax comes for free.
       
   167 [FILLME]
       
   168 
       
   169 
       
   170 Templates
       
   171 ---------
       
   172 
       
   173 *Templates* are specific view that does not depend on a result set. The basic
       
   174 class `Template` (`cubicweb.common.view`) is derived from the class `View`.
       
   175 
       
   176 To build a HTML page, a *main template* is used. In general, the template of
       
   177 identifier `main` is the one (it is not used in case an error is raised or for
       
   178 the login form by example). This template uses other templates in addition
       
   179 to the views which depends on the content to generate the HTML page to return.
       
   180 
       
   181 A *template* is responsible for:
       
   182 
       
   183 1. executing RQL query of data to render if necessarry
       
   184 2. identifying the view to use to render data if it is not specified
       
   185 3. composing the HTML page to return
       
   186 
       
   187 
       
   188 The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`)
       
   189 ------------------------------------------------------------------------------
       
   190 
       
   191 The default main template build the page based on the following pattern:
       
   192 
       
   193 .. image:: images/main_template_layout.png
       
   194 
       
   195 The rectangle containing `view.dispathc()` represents the area where the content
       
   196 view has to be displayed. The others represents sub-templates called to complete
       
   197 the page. A default implementation of those is provided in 
       
   198 `cubicweb.views.basetemplates`. You can, of course, overload those sub-templates
       
   199 to implement your own customization of the HTML page.
       
   200 
       
   201 We can also control certain aspects of the main template thanks to the following
       
   202 forms parameters:
       
   203 
       
   204 * `__notemplate`, if present (whatever the value assigned), only the content view
       
   205   is returned
       
   206 * `__force_display`, if present and its value is not null, no navigation 
       
   207   whatever the number of entities to display
       
   208 * `__method`, if the result set to render contains only one entity and this 
       
   209   parameter is set, it refers to a method to call on the entity by passing it
       
   210   the dictionnary of the forms parameters, before going the classic way (through
       
   211   step 1 and 2 described juste above)
       
   212 
       
   213 .. include:: 05-01-views-stdlib.en.txt
       
   214 
       
   215 
       
   216 XML views, binaries...
       
   217 ----------------------
       
   218 For the views generating other formats that HTML (an image generated dynamically
       
   219 by example), and which can not usually be included in the HTML page generated
       
   220 by the main template (see above), you have to:
       
   221 
       
   222 * set the atribute `templatable` of the class to `False`
       
   223 * set, through the attribute `content_type` of the class, the MIME type generated
       
   224   by the view to `application/octet-stream`
       
   225 
       
   226 For the views dedicated to binary content creation (an image dynamically generated
       
   227 by example), we have to set the attribute `binary` of the class to `True` (which
       
   228 implies that `templateable == False`, so that the attribute `w` of the view could be
       
   229 replaced by a binary flow instead of unicode).
       
   230 
       
   231 (X)HTML tricks to apply
       
   232 -----------------------
       
   233 
       
   234 Some web browser (Firefox by example) are not happy with empty `<div>`
       
   235 (by empty we mean that there is no content in the tag, but there
       
   236 could be attributes), so we should always use `<div></div>` even if
       
   237 it is empty and not use `<div/>`.
       
   238