主视图

默认情况下, CubicWeb 提供适合每个可用实体类型的视图。这是您可能对修改感兴趣的第一个视图。它也是最富有和最复杂的一个。

它在包含实体的单行结果集上自动选择。

它生活在 cubicweb.web.views.primary 模块。

这个 初级的 视图应该提供关于实体的最多信息。

布局

主视图具有以下布局。

../../../_images/primaryview_template.png

主视图配置

如果要自定义实体的主视图,则可能不需要重写主视图类。对于简单的调整(属性或关系显示位置和样式),一种更简单的方法是使用uicfg。

属性/关系显示位置

在主视图中,有三个部分可以显示属性和关系(在上图中以粉红色表示):

  • '属性'

  • '关系'

  • '侧边栏'

属性 只能在“属性”部分中显示(默认

行为)。它们也可以被隐藏。默认情况下,类型的属性 PasswordBytes 是隐藏的。

例如,隐藏 title 的属性 Blog 实体:

from cubicweb.web.views import uicfg
uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')

关系 可以显示在三个部分之一,也可以隐藏。

对于关系,有两种方法:

  • tag_object_of 用于修改对象的主视图

  • tag_subject_of 用于修改主题的主视图

这两种方法有两个参数:

  • 三联体 (subject, relation_name, object) ,其中主题或对象可以替换为 '*'

  • 节名称或 hidden

pv_section = uicfg.primaryview_section
# hide every relation `entry_of` in the `Blog` primary view
pv_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')

# display `entry_of` relations in the `relations`
# section in the `BlogEntry` primary view
pv_section.tag_subject_of(('BlogEntry', 'entry_of', '*'), 'relations')

显示内容

你可以使用 primaryview_display_ctrl 自定义属性或关系的显示。的值 primaryview_display_ctrl 是字典。

属性和关系的通用键是:

  • vid :指定用于显示属性或关系的视图的区域ID。

    如果 vid 未指定,默认值取决于节:
    • attributes 部分:“重新编辑”视图

    • relations 部分:“自动限制”视图

    • sideboxes 部分:“侧边栏”视图

  • order :int用于控制节中的顺序。如果未指定,则根据添加标记的顺序自动设置。

  • label :关系部分或侧框的标签

  • showlabel :布尔值,指示是否显示标签

# let us remind the schema of a blog entry
class BlogEntry(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 definition
view_ctrl = uicfg.primaryview_display_ctrl
for index, attr in enumerate('title', 'content', 'publish_date'):
    view_ctrl.tag_attribute(('BlogEntry', attr), {'order': index})

默认情况下,“关系”部分中显示的关系由“自动限制”视图显示。此视图将使用逗号分隔的值,或者列表视图和/或限制您的RSET(如果其中有太多的项目)(在本例中生成“查看全部”链接)。

您可以通过在 primaryview_display_ctrl 关系标记:

  • limit ,要显示的最大实体数。默认情况下使用“navigation.relevant limit”cwproperty的值(默认为8)。如果没有,就没有限制。

  • use_list_limit ,直到它们显示为列表的实体数(例如使用“列表”视图)。低于该限制,将使用“csv”视图。如果没有,仍然使用“csv”显示。

  • subvid ,子视图标识符(例如列表中每个项应使用的视图)

注意,您也可以使用 filter 键设置一个回调,将相关的结果集作为参数,并返回它进行过滤,例如,执行一些不能使用rql进行的任意过滤。

pv_section = uicfg.primaryview_section
# in `CWUser` primary view, display `created_by`
# relations in relations section
pv_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 comments
def filter_comment(rset):
    return rset.filtered_rset(lambda x: x.e_schema == 'Comment')
pv_ctrl = uicfg.primaryview_display_ctrl
pv_ctrl.tag_object_of(('*', 'created_by', 'CWUser'),
                      {'vid': 'list', 'label': _('latest comment(s):'),
                       'limit': True,
                       'filter': filter_comment})

警告

primaryview_display_ctrl 分别忽略关系的主客体 tag_object_oftag_subject_of .为避免在执行期间出现警告,应将它们设置为 '*' .

定制和创建示例

我们现在将向您展示一个 primary 视图以及如何自定义它。

如果你想改变A的方式 BlogEntry 显示,只需重写该方法 cell_call() 视图的 primary 在里面 BlogDemo/views.py .

from cubicweb.predicates import is_instance
from cubicweb.web.views.primary import Primaryview

class BlogEntryPrimaryView(PrimaryView):
    __select__ = PrimaryView.__select__ & is_instance('BlogEntry')

    def render_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)

上面的源代码为定义了一个新的主视图 BlogEntry . 这个 __reid__ 类属性在那里不重复,因为它是通过 primary.PrimaryView 班级。

此视图的选择器用它自己的特定条件链接继承类的选择器。

视图方法 self.w() 用于输出数据。在这里 lines 08-09 输出条目发布日期的HTML。

博客条目现在看起来好多了

现在让我们改进博客的主要视图

from logilab.mtconverter import xml_escape
from cubicweb.predicates import is_instance, one_line_rset
from cubicweb.web.views.primary import Primaryview

class BlogPrimaryView(PrimaryView):
    __regid__ = 'primary'
    __select__ = PrimaryView.__select__ & is_instance('Blog')
    rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'

    def render_entity_relations(self, entity):
        rset = self._cw.execute(self.rql, {'b' : entity.eid})
        for entry in rset.entities():
            self.w(u'<p>%s</p>' % entry.view('inblogcontext'))

class BlogEntryInBlogView(EntityView):
    __regid__ = 'inblogcontext'
    __select__ = is_instance('BlogEntry')

    def cell_call(self, row, col):
        entity = self.cw_rset.get_entity(row, col)
        self.w(u'<a href="%s" title="%s">%s</a>' %
               entity.absolute_url(),
               xml_escape(entity.content[:50]),
               xml_escape(entity.description))

这在两个地方发生。首先,我们重写博客主视图的呈现实体关系方法。在这里,我们希望以自定义方式显示我们的日志。

AT line 10 ,将发出一个简单的请求来构建一个结果集,其中所有实体都链接到当前 Blog 按关系划分的实体 entry_of .处理请求的框架部分了解模式,并推断这些实体必须属于 BlogEntry 分类并检索它们(按指定的发布日期顺序)。

请求返回一个称为结果集的数据选择。结果集对象有一个.entities()方法,该方法返回请求实体上的生成器(透明地通过 ORM 层)。

AT line 13 视图“inblogcontext”应用于每个日志条目以输出HTML。(请注意,“inblogContext”视图在 CubicWeb .您完全可以自由定义整个视图族。)我们只需要将每个Blogentry输出包装在一个“p”HTML元素中。

接下来,我们定义“inblogContext”视图。这不是主视图,它有定义良好的部分(标题、元数据、属性、关系/框)。所有基本视图都必须定义为单元调用。

由于视图应用于结果集(可以是数据表),因此我们必须从其(行、列)坐标中恢复实体。 (line 20 )。然后我们可以吐一些HTML。

警告

小心:所有的弦都在 CubicWeb 实际上是Unicode字符串。虽然网络浏览器通常能够容忍不连贯的编码,但我们不应该滥用它。因此,我们必须正确地避开我们的数据。必须使用xml_escape()函数从python unicode字符串安全地填充(x)HTML元素。

假设我们在博客中添加了标题为 MyLife ,现在显示它可以读取它的描述和所有条目。

博客及其所有条目