doc/book/fr/05-define-views.fr.txt
brancholdstable
changeset 7074 e4580e5f0703
parent 6749 48f468f33704
parent 7073 4ce9e536dd66
child 7078 bad26a22fe29
child 7083 b8e35cde46e9
equal deleted inserted replaced
6749:48f468f33704 7074:e4580e5f0703
     1 .. -*- coding: utf-8 -*-
       
     2 
       
     3 .. _DefinitionVues:
       
     4 
       
     5 Définition de vues
       
     6 ==================
       
     7 
       
     8 Les classes de base des vues
       
     9 ----------------------------
       
    10 
       
    11 La class `View` (`cubicweb.common.view`)
       
    12 ````````````````````````````````````````
       
    13 Un vue écrit dans son flux de sortie via son attribut `w` (`UStreamIO`).
       
    14 
       
    15 L'interface de base des vues est la suivante :
       
    16 
       
    17 * `dispatch(**context)`, appelle ("rend") la vue en appellent `call` ou
       
    18   `cell_call` en fonction des arguments passé
       
    19 * `call(**kwargs)`, appelle la vue pour un result set complet ou nul
       
    20 * `cell_call(row, col, **kwargs)`, appelle la vue pour une cellule donnée d'un
       
    21   result set
       
    22 * `url()`, retourne l'url permettant d'obtenir cette vue avec le result set en
       
    23   cours
       
    24 * `view(__vid, rset, __fallback_vid=None, **kwargs)`, appelle la vue
       
    25   d'identificant `__vid` sur le result set donné. Il est possible de données un
       
    26   identificant de vue de "fallback" qui sera utilisé si la vue demandée n'est
       
    27   pas applicable au result set
       
    28 
       
    29 * `wview(__vid, rset, __fallback_vid=None, **kwargs)`, pareil que `view` mais
       
    30   passe automatiquement le flux en argument
       
    31 
       
    32 * `html_headers()`, retourne une liste d'en-tête HTML à placer par le template
       
    33   principal
       
    34 
       
    35 * `page_title()`, retourne le titre à utiliser dans l'en tête HTML `title`
       
    36 
       
    37 * `creator(eid)`, retourne l'eid et le login du créateur de l'entité ayant
       
    38   l'eid passé en argument
       
    39 
       
    40 Autres classes de base :
       
    41 
       
    42 * `EntityView`, vue s'appliquant à aux lignes ou cellule contenant une entité
       
    43   (eg un eid)
       
    44 * `StartupView`, vue de départ n'ayant pas besoin de result set
       
    45 * `AnyRsetView`, vue s'appliquant à n'importe quelle result set
       
    46 
       
    47 Le mecanisme de selection de vues
       
    48 ---------------------------------
       
    49 
       
    50 Pour un identifiant de vue donne, plusieurs vues peuvent etre definies.
       
    51 `CubicWeb` utilise un selecteur qui permet de calculer un score et d'identifier
       
    52 la vue la plus appropriee a appliquer dans le contexte. La librairie du selecteur
       
    53 se trouve dans ``cubicweb.common.selector`` et une librairie des methodes utilisees
       
    54 pour calculer les scores est dans ``cubicweb.vregistry.vreq``.
       
    55 
       
    56 [FROM-LAX-BOOK]
       
    57 
       
    58 Tip: when modifying views, you do not need to restart the local
       
    59 server. Just save the file in your editor and reload the page in your
       
    60 browser to see the changes.
       
    61 
       
    62 With `LAX`, views are defined by Python classes. A view includes :
       
    63 
       
    64 - an identifier (all objects in `LAX` are entered in a registry
       
    65   and this identifier will be used as a key)
       
    66 
       
    67 - a filter to select the resulsets it can be applied to
       
    68 
       
    69 `LAX` provides a lot of standard views, for a complete list, you
       
    70 will have to read the code in directory ``ginco/web/views/`` (XXX
       
    71 improve doc).
       
    72 
       
    73 For example, the view named ``primary`` is the one used to display
       
    74 a single entity.
       
    75 
       
    76 If you want to change the way a ``BlogEntry`` is displayed, just
       
    77 override the view ``primary`` in ``BlogDemo/views.py`` ::
       
    78 
       
    79   01. from ginco.web.views import baseviews
       
    80   02.
       
    81   03. class BlogEntryPrimaryView(baseviews.PrimaryView):
       
    82   04.
       
    83   05.     accepts = ('BlogEntry',)
       
    84   06.
       
    85   07.     def cell_call(self, row, col):
       
    86   08.         entity = self.rset.get_entity(row, col)
       
    87   09.         self.w(u'<h1>%s</h1>' % entity.title)
       
    88   10.         self.w(u'<p>published on %s in category %s</p>' % \
       
    89   11.                (entity.publish_date.strftime('%Y-%m-%d'), entity.category))
       
    90   12.         self.w(u'<p>%s</p>' % entity.text)
       
    91 
       
    92 The above source code defines a new primary view (`line 03`) for
       
    93 ``BlogEntry`` (`line 05`).
       
    94 
       
    95 Since views are applied to resultsets and resulsets can be tables of
       
    96 data, it is needed to recover the entity from its (row,col)
       
    97 coordinates (`line 08`). We will get to this in more detail later.
       
    98 
       
    99 The view has a ``self.w()`` method that is used to output data. Here `lines
       
   100 09-12` output HTML tags and values of the entity's attributes.
       
   101 
       
   102 When displaying same blog entry as before, you will notice that the
       
   103 page is now looking much nicer.
       
   104 
       
   105 .. image:: images/lax-book.09-new-view-blogentry.fr.png
       
   106    :alt: blog entries now look much nicer
       
   107 
       
   108 Let us now improve the primary view of a blog ::
       
   109 
       
   110   01. class BlogPrimaryView(baseviews.PrimaryView):
       
   111   02.
       
   112   03.     accepts = ('Blog',)
       
   113   04.
       
   114   05.     def cell_call(self, row, col):
       
   115   06.         entity = self.rset.get_entity(row, col)
       
   116   07.         self.w(u'<h1>%s</h1>' % entity.title)
       
   117   08.         self.w(u'<p>%s</p>' % entity.description)
       
   118   09.         rset = self.req.execute('Any E WHERE E entry_of B, B eid "%s"' % entity.eid)
       
   119   10.         self.wview('primary', rset)
       
   120 
       
   121 In the above source code, `lines 01-08` are similar to the previous
       
   122 view we defined.
       
   123 
       
   124 At `line 09`, a simple request in made to build a resultset with all
       
   125 the entities linked to the current ``Blog`` entity by the relationship
       
   126 ``entry_of``. The part of the framework handling the request knows
       
   127 about the schema and infer that such entities have to be of the
       
   128 ``BlogEntry`` kind and retrieves them.
       
   129 
       
   130 The request returns a selection of data called a resultset. At
       
   131 `line 10` the view 'primary' is applied to this resultset to output
       
   132 HTML.
       
   133 
       
   134 **This is to be compared to interfaces and protocols in object-oriented
       
   135 languages. Applying a given view to all the entities of a resultset only
       
   136 requires the availability, for each entity of this resultset, of a
       
   137 view with that name that can accepts the entity.**
       
   138 
       
   139 Assuming we added entries to the blog titled `MyLife`, displaying it
       
   140 now allows to read its description and all its entries.
       
   141 
       
   142 .. image:: images/lax-book.10-blog-with-two-entries.fr.png
       
   143    :alt: a blog and all its entries
       
   144 
       
   145 **Before we move forward, remember that the selection/view principle is
       
   146 at the core of `LAX`. Everywhere in the engine, data is requested
       
   147 using the RQL language, then HTML/XML/text/PNG is output by applying a
       
   148 view to the resultset returned by the query. That is where most of the
       
   149 flexibility comes from.**
       
   150 
       
   151 [WRITE ME]
       
   152 
       
   153 * implementing interfaces, calendar for blog entries
       
   154 * show that a calendar view can export data to ical
       
   155 
       
   156 We will implement the ginco.interfaces.ICalendarable interfaces on
       
   157 entities.BloEntry and apply the OneMonthCalendar and iCalendar views
       
   158 to resultsets like "Any E WHERE E is BlogEntry"
       
   159 
       
   160 * create view "blogentry table" with title, publish_date, category
       
   161 
       
   162 We will show that by default the view that displays
       
   163 "Any E,D,C WHERE E publish_date D, E category C" is the table view.
       
   164 Of course, the same can be obtained by calling
       
   165 self.wview('table',rset)
       
   166 
       
   167 * in view blog, select blogentries and apply view "blogentry table"
       
   168 * demo ajax by filtering blogentry table on category
       
   169 
       
   170 we did the same with 'primary', but with tables we can turn on filters
       
   171 and show that ajax comes for free.
       
   172 [FILLME]
       
   173 
       
   174 Les templates ou patron
       
   175 -----------------------
       
   176 
       
   177 Les patrons (ou *template*) sont des cas particulier de vue ne dépendant a
       
   178 priori pas d'un result set. La classe de base `Template` (`cubicweb.common.view`)
       
   179 est une classe dérivée de la classe `View`.
       
   180 
       
   181 Pour construire une page HTML, un *template principal* est utilisé. Généralement
       
   182 celui possédant l'identifiant 'main' est utilisé (ce n'est pas le cas lors
       
   183 d'erreur dans celui-ci ou pour le formulaire de login par exemple). Ce patron
       
   184 utilise d'autres patrons en plus des vues dépendants du contenu pour générer la
       
   185 page à renvoyer.
       
   186 
       
   187 C'est ce template qui est chargé :
       
   188 
       
   189 1. d'éxécuter la requête RQL des données à afficher le cas échéant
       
   190 2. éventuellement de déterminer la vue à utiliser pour l'afficher si non
       
   191    spécifiée
       
   192 3. de composer la page à retourner
       
   193 
       
   194 
       
   195 Le patron principal par défaut (`cubicweb.web.views.basetemplates.TheMainTemplate`)
       
   196 -----------------------------------------------------------------------------------
       
   197 
       
   198 Le template principal par défaut construit la page selon la décomposition
       
   199 suivante :
       
   200 
       
   201 .. image:: images/main_template_layout.png
       
   202 
       
   203 Le rectancle contenant le `view.dispatch()` représente l'emplacement où est
       
   204 inséré la vue de contenu à afficher. Les autres représentent des sous-templates
       
   205 appelé pour construire la page. Les implémentations par défaut de tout ces
       
   206 templates sont dans le module `cubicweb.web.views.basetemplates`. Vous pouvez
       
   207 évidemment surcharger l'un des sous-templates pour modifier l'aspect visuel
       
   208 d'une partie désirée de la page.
       
   209 
       
   210 On peut également contrôler certains comportements du template principal à
       
   211 l'aide des paramètres de formulaire suivante :
       
   212 
       
   213 * `__notemplate`, si présente (quelque soit la valeur associée), seule la vue de
       
   214   contenu est renvoyée
       
   215 * `__force_display`, si présente et contient une valeur non nulle, pas de
       
   216   navigation quelque soit le nombre d'entités à afficher
       
   217 * `__method`, si le result set à afficher ne contient qu'une entité et que ce
       
   218   paramètre est spécifié, celui-ci désigne une méthode à appeler sur l'entité
       
   219   en lui donnant en argument le dictionnaire des paramètres de formulaire, avant
       
   220   de reprendre le comportement classique (s'insère entre les étapes 1. et
       
   221   2. décrites ci-dessus)
       
   222 
       
   223 
       
   224 .. include:: 05-01-views-stdlib.fr.txt
       
   225 
       
   226 
       
   227 Vues xml, binaires...
       
   228 ---------------------
       
   229 Pour les vues générants autre que du html  (une image générée dynamiquement par
       
   230 exemple), et qui ne peuvent donc généralement pas être incluse dans la page
       
   231 HTML générée par le template principal (voir ci-dessus), il faut :
       
   232 
       
   233 * placer l'attribut `templatable` de la classe à `False`
       
   234 * indiquer via l'attribut `content_type` de la classe le type MIME généré par la
       
   235   vue 'application/octet-stream'
       
   236 
       
   237 Pour les vues générants un contenu binaire (une image générée dynamiquement par
       
   238 exemple), il faut également placer l'attribut `binary` de la classe à `True` (ce
       
   239 qui implique `templatable == False` afin que l'attribut `w` de la vue soit
       
   240 remplacé par un flux binaire plutôt que unicode.
       
   241 
       
   242 
       
   243 Quelques trucs (X)HTML à respecter
       
   244 ----------------------------------
       
   245 Certains navigateurs (dont firefox) n'aime pas les `<div>` vides (par vide
       
   246 j'entend sans contenu dans la balise, il peut y avoir des attributs), faut
       
   247 toujours mettre `<div></div>` même s'il n'y a rien dedans, et non `<div/>`.