Unlike Kanban views, the QWeb templates in reports are rendered server side, and use a Python QWeb implementation. We can see this as two implementations of the same specification, and there are some differences that we need to be aware of.

To start with, QWeb expressions are evaluated using Python syntax, not JavaScript. For the simplest expressions, there may be little or no difference, but more complex operations will probably be different.

The way expressions are evaluated is also different. For reports, we have the following variables available:

The report content is written in HTML, field values can be referenced using the t-field attribute, and it can be complemented with the t-field-options attribute to use a specific widget to render the field content.

Now we can start designing the page content for our report:

<!-- Report page content  
<div class="row bg-primary"> 
  <div class="col-xs-3"> 
    <span class="glyphicon glyphicon-pushpin" /> 
      What 
  </div> 
  <div class="col-xs-2">Who</div> 
  <div class="col-xs-1">When</div> 
  <div class="col-xs-3">Where</div> 
  <div class="col-xs-3">Watchers</div> 
</div> 
 
<t t-foreach="docs" t-as="o"> 
  <div class="row"> 
    <!-- Data Row Content --> 
  </div> 
</t> 

The layout of the content can use the Twitter Bootstrap HTML grid system. In a nutshell, Bootstrap has a grid layout with 12 columns. A new row can be added using <div class="row">. Inside a row, we have cells, each spanning though a certain number of columns, that should take up the 12 columns. Each cell can be defined with row <div class="col-xs-N">, where N is the number of columns it spans.

Here we are adding a header row with titles, and then we have a t-foreach loop, iterating through each record, and rendering a row for each one.

Since the rendering is done server-side, records are objects and we can use dot notation to access fields from related data records. This makes it easy to follow through relational fields to access their data. Notice that this is not possible in client-side rendered Qweb,views, such as the web client kanban views.

This is the XML for the content of the record rows:

<div class="col-xs-3"> 
  <h4><span t-field="o.name" /></h4> 
</div> 
<div class="col-xs-2"> 
  <span t-field="o.user_id" /> 
</div> 
<div class="col-xs-1"> 
  <span t-field="o.date_deadline" /> 
    <span t-field="o.amount_cost" 
      t-field-options='{ 
        "widget": "monetary", 
        "display_currency": "o.currency_id"}'/> 
</div> 
<div class="col-xs-3"> 
  <div t-field="res_company.partner_id" 
    t-field-options='{ 
      "widget": "contact", 
      "fields": ["address", "name", "phone", "fax"], 
                "no_marker": true}' /> 
</div> 
<div class="col-xs-3"> 
  <!-- Render followers --> 
</div> 

As we can see, fields can be used with additional options. These are very similar to the options attribute used on form views, as seen in Chapter 6 , Views - Designing the User Interface, used with an additional widget to set the widget to use to render the field.

An example is the monetary widget, used above, next to the deadline date.

A more sophisticated example is the contact widget, used to format addresses. We used the company address, res_company.partner_id, since it has some default data and we can immediately see the rendered address. But it would make more sense to use the assigned user's address, o.user_id.partner_id. By default the contact widget displays addresses with some pictograms, such as a phone icon. The no_marker="true" option we used disables them.