If you want to customize the primary view of an entity, overriding the primary
view class may not be necessary. For simple adjustments (attributes or relations
display locations and styles), a much simpler way is to use uicfg.

You can use primaryview_display_ctrl to customize the display of attributes
or relations. Values of primaryview_display_ctrl are dictionaries.

Common keys for attributes and relations are:

vid: specifies the regid of the view for displaying the attribute or the relation.

If vid is not specified, the default value depends on the section:

attributes section: ‘reledit’ view

relations section: ‘autolimited’ view

sideboxes section: ‘sidebox’ view

order: int used to control order within a section. When not specified,
automatically set according to order in which tags are added.

label: label for the relations section or side box

showlabel: boolean telling whether the label is displayed

# let us remind the schema of a blog entryclassBlogEntry(EntityType):title=String(required=True,fulltextindexed=True,maxsize=256)publish_date=Date(default='TODAY')content=String(required=True,fulltextindexed=True)entry_of=SubjectRelation('Blog',cardinality='?*')# now, we want to show attributes# with an order different from that in the schema definitionview_ctrl=uicfg.primaryview_display_ctrlforindex,attrinenumerate('title','content','publish_date'):view_ctrl.tag_attribute(('BlogEntry',attr),{'order':index})

By default, relations displayed in the ‘relations’ section are being displayed by
the ‘autolimited’ view. This view will use comma separated values, or list view
and/or limit your rset if there is too much items in it (and generate the “view
all” link in this case).

You can control this view by setting the following values in the
primaryview_display_ctrl relation tag:

limit, maximum number of entities to display. The value of the
‘navigation.related-limit’ cwproperty is used by default (which is 8 by default).
If None, no limit.

use_list_limit, number of entities until which they should be display as a list
(eg using the ‘list’ view). Below that limit, the ‘csv’ view is used. If None,
display using ‘csv’ anyway.

subvid, the subview identifier (eg view that should be used of each item in the
list)

Notice you can also use the filter key to set up a callback taking the related
result set as argument and returning it filtered, to do some arbitrary filtering
that can’t be done using rql for instance.

pv_section=uicfg.primaryview_section# in `CWUser` primary view, display `created_by`# relations in relations sectionpv_section.tag_object_of(('*','created_by','CWUser'),'relations')# display this relation as a list, sets the label,# limit the number of results and filters on commentsdeffilter_comment(rset):returnrset.filtered_rset(lambdax:x.e_schema=='Comment')pv_ctrl=uicfg.primaryview_display_ctrlpv_ctrl.tag_object_of(('*','created_by','CWUser'),{'vid':'list','label':_('latest comment(s):'),'limit':True,'filter':filter_comment})

Warning

with the primaryview_display_ctrl rtag, the subject or the
object of the relation is ignored for respectively tag_object_of or
tag_subject_of. To avoid warnings during execution, they should be set to
'*'.

This method is applicable only for entity type implementing the
interface IPrevNext. This interface is for entities which can be
linked to a previous and/or next entity. This method will render the
navigation links between entities of this type, either at the top or at
the bottom of the page given the context (navcontent{top|bottom}).

Also, please note that by setting the following attributes in your
subclass, you can already customize some of the rendering:

show_attr_label

Renders the attribute label next to the attribute value if set to True.
Otherwise, does only display the attribute value.

show_rel_label

Renders the relation label next to the relation value if set to True.
Otherwise, does only display the relation value.

main_related_section

Renders the relations of the entity if set to True.

A good practice is for you to identify the content of your entity type for
which the default rendering does not answer your need so that you can focus
on the specific method (from the list above) that needs to be modified. We
do not advise you to overwrite render_entity unless you want a
completely different layout.

This view will wrap an attribute value into an ‘<pre>’ HTML tag to display
arbitrary text where EOL will be respected. It usually make sense for
attributes whose value is a multi-lines string where new lines matters.

We’ll show you now an example of a primary view and how to customize it.

If you want to change the way a BlogEntry is displayed, just
override the method cell_call() of the view primary in
BlogDemo/views.py.

fromcubicweb.predicatesimportis_instancefromcubicweb.web.views.primaryimportPrimaryviewclassBlogEntryPrimaryView(PrimaryView):__select__=PrimaryView.__select__&is_instance('BlogEntry')defrender_entity_attributes(self,entity):self.w(u'<p>published on %s</p>'%entity.publish_date.strftime('%Y-%m-%d'))super(BlogEntryPrimaryView,self).render_entity_attributes(entity)

The above source code defines a new primary view for
BlogEntry. The __reid__ class attribute is not repeated there since it
is inherited through the primary.PrimaryView class.

The selector for this view chains the selector of the inherited class
with its own specific criterion.

The view method self.w() is used to output data. Here lines
08-09 output HTML for the publication date of the entry.

This happens in two places. First we override the
render_entity_relations method of a Blog’s primary view. Here we want
to display our blog entries in a custom way.

At line 10, a simple request is made to build a result set with all
the entities linked to the current Blog entity by the relationship
entry_of. The part of the framework handling the request knows
about the schema and infers that such entities have to be of the
BlogEntry kind and retrieves them (in the prescribed publish_date
order).

The request returns a selection of data called a result set. Result
set objects have an .entities() method returning a generator on
requested entities (going transparently through the ORM layer).

At line 13 the view ‘inblogcontext’ is applied to each blog entry to
output HTML. (Note that the ‘inblogcontext’ view is not defined
whatsoever in CubicWeb. You are absolutely free to define whole view
families.) We juste arrange to wrap each blogentry output in a ‘p’
html element.

Next, we define the ‘inblogcontext’ view. This is NOT a primary view,
with its well-defined sections (title, metadata, attribtues,
relations/boxes). All a basic view has to define is cell_call.

Since views are applied to result sets which can be tables of data, we
have to recover the entity from its (row,col)-coordinates (line
20). Then we can spit some HTML.

Warning

Be careful: all strings manipulated in CubicWeb are actually
unicode strings. While web browsers are usually tolerant to
incoherent encodings they are being served, we should not abuse
it. Hence we have to properly escape our data. The xml_escape()
function has to be used to safely fill (X)HTML elements from Python
unicode strings.

Assuming we added entries to the blog titled MyLife, displaying it
now allows to read its description and all its entries.