This module contains table views, with the following features that may be provided (depending on the used implementation):
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.
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:
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.
Default renderer for RsetTableView.
alias of RsetTableColRenderer
returns the index of the first non-attribute variable among the RQL selected variables
return the number of rows (header excluded) to be displayed
This abstract table view is designed to be used with an is_instance() or adaptable predicate, hence doesn’t depend the result set shape as the RsetTableView 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 or RelatedEntityColRenderer renderer for a column in the column_renderers dictionary.
Default column renderer for EntityTableView.
You may use the entity() method to retrieve the main entity for a given row number.
Convenience method returning the table’s main entity.
Sort value if renderfunc nor sortfunc specified at initialization.
This default implementation consider column id is an entity attribute and print its value.
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).
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.
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.
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.
alias of EntityTableColRenderer
Return the table’s main entity
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).
alias of PyValTableColRenderer
return the number of rows (header excluded) to be displayed
All those classes are rendered using a layout:
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:
<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.
There is by default only on 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 can still 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 implements you own class.
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:
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
Abstract base class for column renderer. Interface of a column renderer follows:
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.
Write label for the specified column by calling w().
Write value for the specified cell by calling w().
Parameters: | rownum – the row number in the table |
---|
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:
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.
Return a list of column renderers, one for each column to be rendered. Prototype of a column renderer is described below:
Abstract base class for column renderer. Interface of a column renderer follows:
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.
Write label for the specified column by calling w().
Write value for the specified cell by calling w().
Parameters: | rownum – the row number in the table |
---|
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 |
Return a column renderer for column of the given id.
<wrapped by the cachedproperty decorator>
Return a list of actions (Link) that match the view’s result set, and return those in the ‘mainactions’ category.
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.
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=worpackage_cell,
sortfunc=worpackage_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:
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.