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:
docs
is an iterable collection with the records to printdoc_ids
is a list of the IDs of the records to printdoc_model
identifies the model of the records, todo.task
for exampletime
is is a reference to Python's time libraryuser
is the record for the user running the reportres_company
is the record for the current user's companyThe 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.
A complete reference for Bootstrap, describing these and other style elements, can be found at http://getbootstrap.com .
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.