Warning
Starting from CubicWeb version 4.0 all code related to generating html views has been moved to the Cube cubicweb_web.
If you want to migrate a project from 3.38 to 4.* while still using all the
html views you need to both install the cubicweb_web cube AND add it to
your dependencies and run add_cube('web')
.
cubicweb_web can be installed from pypi this way:
pip install cubicweb_web
We donât plan to maintain the features in cubicweb_web in the long run; we are moving to a full javascript frontend using both cubicweb_api (which exposes a HTTP API) and @cubicweb/client as a frontend javascript toolkit.
In the long run cubicweb_api will be merged inside of CubicWeb.
Table views#
This module contains table views, with the following features that may be provided (depending on the used implementation):
facets filtering
pagination
actions menu
properly sortable content
odd/row/hover line styles
The three main implementation are described below. Each implementation is suitable for a particular case, but they each attempt to display tables that looks similar.
- class cubicweb_web.views.tableview.RsetTableView(req=None, rset=None, **kwargs)[source]#
This table view accepts any non-empty rset. It uses introspection on the result set to compute column names and the proper way to display the cells.
It is highly configurable and accepts a wealth of options, but take care to check what youâre trying to achieve wouldnât be a job for the
EntityTableView
. Basically the question is: does this view should be tied to the result set queryâs shape or no? If yes, than youâre fine. If no, you should take a look at the other table implementation.The following class attributes may be used to control the table:
finalvid, a view identifier that should be called on final entities (e.g. attribute values). Default to âfinalâ.
nonfinalvid, a view identifier that should be called on entities. Default to âincontextâ.
displaycols, if not None, should be a list of rsetâs columns to be displayed.
headers, if not None, should be a list of headers for the tableâs columns. None values in the list will be replaced by computed column names.
cellvids, if not None, should be a dictionary with table column index as key and a view identifier as value, telling the view that should be used in the given column.
Notice displaycols, headers and cellvids may be specified at selection time but then the table wonât have pagination and shouldnât be configured to display the facets filter nor actions (as they wouldnât behave as expected).
This table class use the
RsetTableColRenderer
as default column renderer.- class RsetTableColRenderer(cellvid, **kwargs)#
Default renderer for
RsetTableView
.
- build_column_renderers()[source]#
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
- class AbstractColumnRenderer(header=None, addcount=False, trheader=True, escapeheader=True, sortable=True)#
Abstract base class for column renderer. Interface of a column renderer follows:
- AbstractColumnRenderer.bind(view, colid)#
Bind the column renderer to its view. This is where _cw, view, colid are set and the method to override if you want to add more view/request depending attributes on your column render.
- AbstractColumnRenderer.render_header(w)#
Write label for the specified column by calling w().
- AbstractColumnRenderer.render_cell(w, rownum)#
Write value for the specified cell by calling w().
- Parameters
rownum â the row number in the table
- AbstractColumnRenderer.sortvalue(_rownum)#
Return typed value to be used for sorting on the specified column.
- Parameters
rownum â the row number in the table
Attributes on this base class are:
- Attr
header, the column header. If None, default to _(colid)
- Attr
addcount, if True, add the table size in parenthezis beside the header
- Attr
trheader, should the header be translated
- Attr
escapeheader, should the header be xml_escaped
- Attr
sortable, tell if the column is sortable
- Attr
view, the table view
- Attr
_cw, the request object
- Attr
colid, the column identifier
- Attr
attributes, dictionary of attributes to put on the HTML tag when the cell is rendered
- call(headers=None, displaycols=None, cellvids=None, paginate=None)[source]#
the view is called for an entire result set, by default loop other rows of the result set and call the same view on the particular row
Views applicable on None result sets have to override this method
- default_column_renderer_class#
alias of
cubicweb_web.views.tableview.RsetTableColRenderer
- linkable()[source]#
return True if the view may be linked in a menu
by default views without title are not meant to be displayed
- main_var_index()[source]#
returns the index of the first non-attribute variable among the RQL selected variables
- property table_size#
return the number of rows (header excluded) to be displayed
- class cubicweb_web.views.tableview.EntityTableView(req=None, rset=None, **kwargs)[source]#
This abstract table view is designed to be used with an
is_instance()
oradaptable
predicate, hence doesnât depend the result set shape as theRsetTableView
does.It will display columns that should be defined using the columns class attribute containing a list of column ids. By default, each column is renderered by
EntityTableColRenderer
which consider that the column id is an attribute of the tableâs main entity (ie the one for which the view is selected).You may wish to specify
MainEntityColRenderer
orRelatedEntityColRenderer
renderer for a column in thecolumn_renderers
dictionary.- class EntityTableColRenderer(renderfunc=None, sortfunc=None, sortable=None, **kwargs)#
Default column renderer for
EntityTableView
.You may use the
entity()
method to retrieve the main entity for a given row number.- EntityTableColRenderer.entity(rownum)#
Convenience method returning the tableâs main entity.
- EntityTableColRenderer.render_entity(w, entity)#
Sort value if renderfunc nor sortfunc specified at initialization.
This default implementation consider column id is an entity attribute and print its value.
- EntityTableColRenderer.entity_sortvalue(entity)#
Cell rendering implementation if renderfunc nor sortfunc specified at initialization.
This default implementation consider column id is an entity attribute and return its sort value by calling entity.sortvalue(colid).
- class MainEntityColRenderer(vid='incontext', addcount=True, **kwargs)#
Renderer to be used for the column displaying the âmain entityâ of a
EntityTableView
.By default display it using the âincontextâ view. You may specify another view identifier using the vid argument.
If header not specified, it would be built using entity types in the main column.
- class RelatedEntityColRenderer(getrelated, addcount=False, **kwargs)#
Renderer to be used for column displaying an entity related the âmain entityâ of a
EntityTableView
.By default display it using the âincontextâ view. You may specify another view identifier using the vid argument.
If header not specified, it would be built by translating the column id.
- class RelationColRenderer(role='subject', vid='csv', subvid=None, fallbackvid='empty-cell', is_rtype_view=False, **kwargs)#
Renderer to be used for column displaying a list of entities related the âmain entityâ of a
EntityTableView
. By default, the main entity is considered as the subject of the relation but you may specify otherwise using the role argument.By default display the related rset using the âcsvâ view, using âoutofcontextâ sub-view for each entity. You may specify another view identifier using respectivly the vid and subvid arguments.
If you specify a ârtype viewâ, such as âreleditâ, you should add a is_rtype_view=True parameter.
If header not specified, it would be built by translating the column id, properly considering role.
- build_column_renderers()[source]#
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
- class AbstractColumnRenderer(header=None, addcount=False, trheader=True, escapeheader=True, sortable=True)#
Abstract base class for column renderer. Interface of a column renderer follows:
- AbstractColumnRenderer.bind(view, colid)#
Bind the column renderer to its view. This is where _cw, view, colid are set and the method to override if you want to add more view/request depending attributes on your column render.
- AbstractColumnRenderer.render_header(w)#
Write label for the specified column by calling w().
- AbstractColumnRenderer.render_cell(w, rownum)#
Write value for the specified cell by calling w().
- Parameters
rownum â the row number in the table
- AbstractColumnRenderer.sortvalue(_rownum)#
Return typed value to be used for sorting on the specified column.
- Parameters
rownum â the row number in the table
Attributes on this base class are:
- Attr
header, the column header. If None, default to _(colid)
- Attr
addcount, if True, add the table size in parenthezis beside the header
- Attr
trheader, should the header be translated
- Attr
escapeheader, should the header be xml_escaped
- Attr
sortable, tell if the column is sortable
- Attr
view, the table view
- Attr
_cw, the request object
- Attr
colid, the column identifier
- Attr
attributes, dictionary of attributes to put on the HTML tag when the cell is rendered
- call(columns=None, **kwargs)[source]#
the view is called for an entire result set, by default loop other rows of the result set and call the same view on the particular row
Views applicable on None result sets have to override this method
- default_column_renderer_class#
alias of
cubicweb_web.views.tableview.EntityTableColRenderer
- property table_size#
Return the number of rows (header excluded) to be displayed.
By default return the number of rows in the viewâs result set. If your table isnât reult set based, override this method.
- class cubicweb_web.views.pyviews.PyValTableView(req, pyvalue, headers=None, cssclass=None, header_column_idx=None, **kwargs)[source]#
This table view is designed to be used a list of list of unicode values given as a mandatory pyvalue argument. Take care, content is NOT xml-escaped.
Itâs configured through the following selection arguments.
If headers is specified, it is expected to be a list of headers to be inserted as first row (in <thead>).
header_column_idx may be used to specify a column index or a set of column indiced where values should be inserted inside <th> tag instead of <td>.
cssclass is the CSS class used on the <table> tag, and default to âlistingâ (so that the table will look similar to those generated by the table view).
- build_column_renderers()[source]#
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
- class AbstractColumnRenderer(header=None, addcount=False, trheader=True, escapeheader=True, sortable=True)#
Abstract base class for column renderer. Interface of a column renderer follows:
- AbstractColumnRenderer.bind(view, colid)#
Bind the column renderer to its view. This is where _cw, view, colid are set and the method to override if you want to add more view/request depending attributes on your column render.
- AbstractColumnRenderer.render_header(w)#
Write label for the specified column by calling w().
- AbstractColumnRenderer.render_cell(w, rownum)#
Write value for the specified cell by calling w().
- Parameters
rownum â the row number in the table
- AbstractColumnRenderer.sortvalue(_rownum)#
Return typed value to be used for sorting on the specified column.
- Parameters
rownum â the row number in the table
Attributes on this base class are:
- Attr
header, the column header. If None, default to _(colid)
- Attr
addcount, if True, add the table size in parenthezis beside the header
- Attr
trheader, should the header be translated
- Attr
escapeheader, should the header be xml_escaped
- Attr
sortable, tell if the column is sortable
- Attr
view, the table view
- Attr
_cw, the request object
- Attr
colid, the column identifier
- Attr
attributes, dictionary of attributes to put on the HTML tag when the cell is rendered
- default_column_renderer_class#
alias of
cubicweb_web.views.pyviews.PyValTableColRenderer
- domid = None#
- property has_headers#
bool(x) -> bool
Returns True when the argument x is true, False otherwise. The builtins True and False are the only two instances of the class bool. The class bool is a subclass of the class int, and cannot be subclassed.
- property layout_args#
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping objectâs
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- table_actions()[source]#
Return a list of actions (
Link
) that match the viewâs result set, and return those in the âmainactionsâ category.
- property table_size#
return the number of rows (header excluded) to be displayed
All those classes are rendered using a layout:
- class cubicweb_web.views.tableview.TableLayout(req, view, **kwargs)[source]#
The default layout for table. When render is called, this will use the API described on
TableMixIn
to feed the generated table.This layout behaviour may be customized using the following attributes / selection arguments:
cssclass, a string that should be used as HTML class attribute. Default to âlistingâ.
needs_css, the CSS files that should be used together with this table. Default to (âcubicweb.tablesorter.cssâ, âcubicweb.tableview.cssâ).
needs_js, the Javascript files that should be used together with this table. Default to (âjquery.tablesorter.jsâ,)
display_filter, tells if the facets filter should be displayed when possible. Allowed values are: - None, donât display it - âtopâ, display it above the table - âbottomâ, display it below the table
display_actions, tells if a menu for available actions should be displayed when possible (see two following options). Allowed values are: - None, donât display it - âtopâ, display it above the table - âbottomâ, display it below the table
hide_filter, when true (the default), facets filter will be hidden by default, with an action in the actions menu allowing to show / hide it.
show_all_option, when true, a show all results link will be displayed below the navigation component.
add_view_actions, when true, actions returned by view.table_actions() will be included in the actions menu.
header_column_idx, if not None, should be a colum index or a set of column index where <th> tags should be generated instead of <td>
- initial_load#
<wrapped by the cachedproperty decorator> We detect a bit heuristically if we are built for the first time or
from subsequent calls by the form filter or by the pagination hooks.
- render(w, **kwargs)[source]#
called to render a view object for a result set.
This method is a dispatched to an actual method selected according to optional row and col parameters, which are locating a particular row or cell in the result set:
if row is specified, cell_call is called
if none of them is supplied, the view is considered to apply on the whole result set (which may be None in this case), call is called
There is by default only one table layout, using the âtable_layoutâ identifier,
that is referenced by table views
cubicweb_web.views.tableview.TableMixIn.layout_id
. If you want to
customize the look and feel of your table, you can either replace the default
one by yours, having multiple variants with proper selectors, or change the
layout_id identifier of your table to use your table specific implementation.
Notice you can gives options to the layout using a layout_args dictionary on your class.
If you still canât find a view that suit your needs, you should take a look at the class below that is the common abstract base class for the three views defined above and implement your own class.
- class cubicweb_web.views.tableview.TableMixIn[source]#
Abstract mix-in class for layout based tables.
This default implementationâs call method simply delegate to meth:layout_render that will select the renderer whose identifier is given by the
layout_id
attribute.Then it provides some default implementation for various parts of the API used by that layout.
Abstract method you will have to override is:
- build_column_renderers()[source]#
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
- class AbstractColumnRenderer(header=None, addcount=False, trheader=True, escapeheader=True, sortable=True)#
Abstract base class for column renderer. Interface of a column renderer follows:
- AbstractColumnRenderer.bind(view, colid)#
Bind the column renderer to its view. This is where _cw, view, colid are set and the method to override if you want to add more view/request depending attributes on your column render.
- AbstractColumnRenderer.render_header(w)#
Write label for the specified column by calling w().
- AbstractColumnRenderer.render_cell(w, rownum)#
Write value for the specified cell by calling w().
- Parameters
rownum â the row number in the table
- AbstractColumnRenderer.sortvalue(_rownum)#
Return typed value to be used for sorting on the specified column.
- Parameters
rownum â the row number in the table
Attributes on this base class are:
- Attr
header, the column header. If None, default to _(colid)
- Attr
addcount, if True, add the table size in parenthezis beside the header
- Attr
trheader, should the header be translated
- Attr
escapeheader, should the header be xml_escaped
- Attr
sortable, tell if the column is sortable
- Attr
view, the table view
- Attr
_cw, the request object
- Attr
colid, the column identifier
- Attr
attributes, dictionary of attributes to put on the HTML tag when the cell is rendered
You may also want to overridde:
- table_size#
Return the number of rows (header excluded) to be displayed.
By default return the number of rows in the viewâs result set. If your table isnât reult set based, override this method.
The
has_headers
boolean attribute tells if the table has some headers to be displayed. Default to True.- build_column_renderers()[source]#
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
- class AbstractColumnRenderer(header=None, addcount=False, trheader=True, escapeheader=True, sortable=True)#
Abstract base class for column renderer. Interface of a column renderer follows:
- AbstractColumnRenderer.bind(view, colid)#
Bind the column renderer to its view. This is where _cw, view, colid are set and the method to override if you want to add more view/request depending attributes on your column render.
- AbstractColumnRenderer.render_header(w)#
Write label for the specified column by calling w().
- AbstractColumnRenderer.render_cell(w, rownum)#
Write value for the specified cell by calling w().
- Parameters
rownum â the row number in the table
- AbstractColumnRenderer.sortvalue(_rownum)#
Return typed value to be used for sorting on the specified column.
- Parameters
rownum â the row number in the table
Attributes on this base class are:
- Attr
header, the column header. If None, default to _(colid)
- Attr
addcount, if True, add the table size in parenthezis beside the header
- Attr
trheader, should the header be translated
- Attr
escapeheader, should the header be xml_escaped
- Attr
sortable, tell if the column is sortable
- Attr
view, the table view
- Attr
_cw, the request object
- Attr
colid, the column identifier
- Attr
attributes, dictionary of attributes to put on the HTML tag when the cell is rendered
- column_renderer(colid, *args, **kwargs)[source]#
Return a column renderer for column of the given id.
- domid#
<wrapped by the cachedproperty decorator>
- table_actions()[source]#
Return a list of actions (
Link
) that match the viewâs result set, and return those in the âmainactionsâ category.
- property table_size#
Return the number of rows (header excluded) to be displayed.
By default return the number of rows in the viewâs result set. If your table isnât reult set based, override this method.
Example#
Let us take an example from the timesheet cube:
class ActivityResourcesTable(EntityView):
__regid__ = 'activity.resources.table'
__select__ = is_instance('Activity')
def call(self, showresource=True):
eids = ','.join(str(row[0]) for row in self.cw_rset)
rql = ('Any R,D,DUR,WO,DESCR,S,A, SN,RT,WT ORDERBY D DESC '
'WHERE '
' A is Activity, A done_by R, R title RT, '
' A diem D, A duration DUR, '
' A done_for WO, WO title WT, '
' A description DESCR, A in_state S, S name SN, '
' A eid IN (%s)' % eids)
rset = self._cw.execute(rql)
self.wview('resource.table', rset, 'null')
class ResourcesTable(RsetTableView):
__regid__ = 'resource.table'
# notice you may wish a stricter selector to check rql's shape
__select__ = is_instance('Resource')
# my table headers
headers = ['Resource', 'diem', 'duration', 'workpackage', 'description', 'state']
# I want a table where attributes are editable (reledit inside)
finalvid = 'editable-final'
cellvids = {3: 'editable-final'}
# display facets and actions with a menu
layout_args = {'display_filter': 'top',
'add_view_actions': None}
To obtain an editable table, you may specify the âeditable-tableâ view identifier using some of cellvids, finalvid or nonfinalvid.
The previous example results in:

In order to activate table filter mechanism, the display_filter option is given as a layout argument. A small arrow will be displayed at the tableâs top right corner. Clicking on show filter form action, will display the filter form as below:

By the same way, you can display additional actions for the selected entities
by setting add_view_actions layout option to True. This will add actions
returned by the viewâs table_actions()
.
You can notice that all columns of the result set are not displayed. This is because of given headers, implying to display only columns from 0 to len(headers).
Also Notice that the ResourcesTable view relies on a particular rql shape (which is not ensured by the way, the only checked thing is that the result set contains instance of the Resource type). That usually implies that you canât use this view for user specific queries (e.g. generated by facets or typed manually).
So another option would be to write this view using
EntityTableView
, as below.
class ResourcesTable(EntityTableView):
__regid__ = 'resource.table'
__select__ = is_instance('Resource')
# table columns definition
columns = ['resource', 'diem', 'duration', 'workpackage', 'description', 'in_state']
# I want a table where attributes are editable (reledit inside)
finalvid = 'editable-final'
# display facets and actions with a menu
layout_args = {'display_filter': 'top',
'add_view_actions': None}
def workpackage_cell(entity):
activity = entity.reverse_done_in[0]
activity.view('reledit', rtype='done_for', role='subject', w=w)
def workpackage_sortvalue(entity):
activity = entity.reverse_done_in[0]
return activity.done_for[0].sortvalue()
column_renderers = {
'resource': MainEntityColRenderer(),
'workpackage': EntityTableColRenderer(
header='Workpackage',
renderfunc=workpackage_cell,
sortfunc=workpackage_sortvalue,),
'in_state': EntityTableColRenderer(
renderfunc=lambda w,x: w(x.cw_adapt_to('IWorkflowable').printable_state),
sortfunc=lambda x: x.cw_adapt_to('IWorkflowable').printable_state),
}
Notice the following point:
cell_<column>(w, entity) will be searched for rendering the content of a cell. If not found, column is expected to be an attribute of entity.
cell_sortvalue_<column>(entity) should return a typed value to use for javascript sorting or None for not sortable columns (the default).
The
etable_entity_sortvalue()
decorator will set a âsortvalueâ function for the column containing the main entity (the one given as argument to all methods), which will call entity.sortvalue().You can set a column header using the
etable_header_title()
decorator. This header will be translated. If itâs not an already existing msgid, think to mark it using _() (the example supposes headers are schema defined msgid).
Pro/cons of each approach#
EntityTableView
and RsetableView
provides basically the same
set of features, though they donât share the same properties. Letâs try to sum
up pro and cons of each class.
EntityTableView view is:
more verbose, but usually easier to understand
easily extended (easy to add/remove columns for instance)
doesnât rely on a particular rset shape. Simply give it a title and will be listed in the âpossible viewsâ box if any.
RsetTableView view is:
hard to beat to display barely a result set, or for cases where some of headers, displaycols or cellvids could be defined to enhance the table while you donât care about e.g. pagination or facets.
hardly extensible, as you usually have to change places where the view is called to modify the RQL (hence the viewâs result set shape).