diff -r adbf9a24c41e -r 487bcc269d50 doc/book/en/B1020-define-views.en.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/B1020-define-views.en.txt Tue Dec 23 13:28:48 2008 -0800 @@ -0,0 +1,238 @@ +.. -*- coding: utf-8 -*- + +.. _DefinitionVues: + +Views definition +================ + +Basic class for views +--------------------- + +Class `View` (`cubicweb.common.view`) +````````````````````````````````````` + +A view writes in its output exit thanks to its attribute `w` (`UStreamIO`). + +The basic interface for views is as follows: + +* `dispatch(**context)`, render the view by calling `call` or + `cell_call` depending on the given parameters +* `call(**kwargs)`, call the view for a complete result set or null +* `cell_call(row, col, **kwargs)`, call the view for a given cell of a result set +* `url()`, returns the URL enabling us to get the view with the current + result set +* `view(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of identifier + `__vid` on the given result set. It is possible to give a view identifier + of fallback that will be used if the view requested is not applicable to the + result set + +* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, similar to `view` except + the flow is automatically passed in the parameters + +* `html_headers()`, returns a list of HTML headers to set by the main template + +* `page_title()`, returns the title to use in the HTML header `title` + +* `creator(eid)`, returns the eid and the login of the entity creator of the entity + having the eid given in the parameter + +Other basic classes: + +* `EntityView`, view applying to lines or cell containing an entity (e.g. an eid) +* `StartupView`, start view that does not require a result set to apply to +* `AnyRsetView`, view applied to any result set + + +The selection view principle +---------------------------- + +A view includes : + +- an identifier (all objects in `LAX` are entered in a registry + and this identifier will be used as a key) + +- a filter to select the resulsets it can be applied to + + +For a given identifier, multiple views can be defined. `CubicWeb` uses +a selector which computes scores so that it can identify and select the +best view to apply in context. The selector library is in +``cubicweb.common.selector`` and a library of the methods used to +compute scores is in ``cubicweb.vregistry.vreq``. + + +`CubicWeb` provides a lot of standard views, for a complete list, you +will have to read the code in directory ``cubicweb/web/views/`` (XXX +improve doc). + +For example, the view named ``primary`` is the one used to display +a single entity. + +If you want to change the way a ``BlogEntry`` is displayed, just +override the view ``primary`` in ``BlogDemo/views.py`` :: + + 01. from ginco.web.views import baseviews + 02. + 03. class BlogEntryPrimaryView(baseviews.PrimaryView): + 04. + 05. accepts = ('BlogEntry',) + 06. + 07. def cell_call(self, row, col): + 08. entity = self.entity(row, col) + 09. self.w(u'

%s

' % entity.title) + 10. self.w(u'

published on %s in category %s

' % \ + 11. (entity.publish_date.strftime('%Y-%m-%d'), entity.category)) + 12. self.w(u'

%s

' % entity.text) + +The above source code defines a new primary view (`line 03`) for +``BlogEntry`` (`line 05`). + +Since views are applied to resultsets and resulsets can be tables of +data, it is needed to recover the entity from its (row,col) +coordinates (`line 08`). We will get to this in more detail later. + +The view has a ``self.w()`` method that is used to output data. Here `lines +09-12` output HTML tags and values of the entity's attributes. + +When displaying same blog entry as before, you will notice that the +page is now looking much nicer. + +.. 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 :: + + 01. class BlogPrimaryView(baseviews.PrimaryView): + 02. + 03. accepts = ('Blog',) + 04. + 05. def cell_call(self, row, col): + 06. entity = self.entity(row, col) + 07. self.w(u'

%s

' % entity.title) + 08. self.w(u'

%s

' % entity.description) + 09. rset = self.req.execute('Any E WHERE E entry_of B, B eid "%s"' % entity.eid) + 10. self.wview('primary', rset) + +In the above source code, `lines 01-08` are similar to the previous +view we defined. + +At `line 09`, a simple request in made to build a resultset 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 infer that such entities have to be of the +``BlogEntry`` kind and retrieves them. + +The request returns a selection of data called a resultset. At +`line 10` the view 'primary' is applied to this resultset to output +HTML. + +**This is to be compared to interfaces and protocols in object-oriented +languages. Applying a given view to all the entities of a resultset only +requires the availability, for each entity of this resultset, of a +view with that name that can accepts the entity.** + +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 resultset 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 cubicwweb.interfaces.ICalendarable interfaces on +entities.BloEntry and apply the OneMonthCalendar and iCalendar views +to resultsets 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] + + +Templates +--------- + +*Templates* are specific view that does not depend on a result set. The basic +class `Template` (`cubicweb.common.view`) is derived from the class `View`. + +To build a HTML page, a *main template* is used. In general, the template of +identifier `main` is the one (it is not used in case an error is raised or for +the login form for example). This template uses other templates in addition +to the views which depends on the content to generate the HTML page to return. + +A *template* is responsible for: + +1. executing RQL query of data to render if necessarry +2. identifying the view to use to render data if it is not specified +3. composing the HTML page to return + + +The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`) +------------------------------------------------------------------------------ + +The default main template build the page based on the following pattern: + +.. image:: images/main_template_layout.png + +The rectangle containing `view.dispathc()` represents the area where the content +view has to be displayed. The others represents sub-templates called to complete +the page. A default implementation of those is provided in +`cubicweb.views.basetemplates`. You can, of course, overload those sub-templates +to implement your own customization of the HTML page. + +We can also control certain aspects of the main template thanks to the following +forms parameters: + +* `__notemplate`, if present (whatever the value assigned), only the content view + is returned +* `__force_display`, if present and its value is not null, no navigation + whatever the number of entities to display +* `__method`, if the result set to render contains only one entity and this + parameter is set, it refers to a method to call on the entity by passing it + the dictionnary of the forms parameters, before going the classic way (through + step 1 and 2 described juste above) + +.. include:: B031-views-stdlib.en.txt + + +XML views, binaries... +---------------------- +For the views generating other formats that HTML (an image generated dynamically +for example), and which can not usually be included in the HTML page generated +by the main template (see above), you have to: + +* set the atribute `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` + +For the views dedicated to binary content creation (an image dynamically generated +for example), we have to set the attribute `binary` of the class to `True` (which +implies that `templateable == False`, so that the attribute `w` of the view could be +replaced by a binary flow instead of unicode). + +(X)HTML tricks to apply +----------------------- + +Some web browser (Firefox for example) are not happy with empty `
` +(by empty we mean that there is no content in the tag, but there +could be attributes), so we should always use `
` even if +it is empty and not use `
`. +