2. 注册表、选择器和应用程序对象¶
本章讨论了 CubicWeb 使其不同于其他框架的框架(可能不容易一眼就掌握)。能够做先进的发展 CubicWeb 你需要很好地理解下面的解释。
这一章深入讨论细节。你不必把它们都记住,但要记住,这样你以后就可以回去了。
AppObjects、VRegistry和选择器的概述在 注册表和应用程序对象 章。
2.1. 这个 CWRegistryStore
¶
这个 CWRegistryStore
可以看作是两级词典。它包含所有动态加载的对象(子类 AppObject
)建立 CubicWeb 应用程序。基本上:
第一级键返回 登记处 .此键对应于 __registry__ 应用程序对象类的属性
第二级键返回共享相同标识符的应用程序对象列表。此键对应于 __regid__ 应用程序对象类的属性。
A 登记处 保存特定类型的应用程序对象。例如,实体类有一个注册表,视图有一个注册表等…
这个 CWRegistryStore
有两个主要职责:
是所有注册表的访问点
在启动时以及在调试模式下自动重新加载期间处理注册过程。
2.1.1. 记录过程的详细信息¶
启动时, CubicWeb 加载在其库和实例使用的多维数据集中定义的应用程序对象。首先加载库中的应用程序对象,然后按依赖关系顺序加载多维数据集提供的对象(例如,如果多维数据集依赖于其他对象,则将首先加载依赖关系中的对象)。多维数据集中模块或包的布局在 立方体的标准结构 .
对于每个模块:
默认情况下,所有对象都自动注册
如果某些对象必须替换其他对象,或者只有满足某些条件时才必须包含这些对象,则必须定义 registration_callback(vreg) 模块中的函数并显式注册 所有对象 在这个模块中,使用下面定义的API。
注解
一旦函数 registration_callback(vreg) 是在一个模块中实现的,该模块中的所有对象都必须显式注册,因为它禁用了自动对象注册。
2.1.2. 对象注册的API¶
以下是您可以在 registration_callback 将对象注册到 CWRegistryStore
作为参数给出的实例(通常命名为 vreg ):
register_all()
register_and_replace()
register()
unregister()
实例:
# web/views/basecomponents.py
def registration_callback(vreg):
# register everything in the module except SeeAlsoComponent
vreg.register_all(globals().itervalues(), __name__, (SeeAlsoVComponent,))
# conditionally register SeeAlsoVComponent
if 'see_also' in vreg.schema:
vreg.register(SeeAlsoVComponent)
在这个示例中,我们注册模块中定义的所有应用程序对象类,除了 SeeAlsoVComponent .只有在实例的架构中定义了“see_also”关系类型时,才会注册此类。
# goa/appobjects/sessions.py
def registration_callback(vreg):
vreg.register(SessionsCleaner)
# replace AuthenticationManager by GAEAuthenticationManager
vreg.register_and_replace(GAEAuthenticationManager, AuthenticationManager)
# replace PersistentSessionManager by GAEPersistentSessionManager
vreg.register_and_replace(GAEPersistentSessionManager, PersistentSessionManager)
在本例中,我们逐个显式注册类:
这个 SessionCleaner 类
这个 GAEAuthenticationManager 替换 AuthenticationManager
这个 GAEPersistentSessionManager 替换 PersistentSessionManager
如果在某个时候我们在这个模块中注册了一个新的AppObject类,那么如果不修改 registration_callback 实施。不过,由于调用了 register_all 方法。
2.1.3. 运行时对象选择¶
既然已经加载了所有的应用程序对象,问题是:当我想要某个特定的对象时,例如给定实体的主视图,我如何获得正确的对象?这就是我们所说的 选择机制 .
如中所述 的核心概念 CubicWeb 章节:
每个应用程序对象都有一个 选择器 ,由其定义 __select__ 类属性
此选择器负责返回 分数 对于给定的上下文
0分表示对象不适用于此上下文
否则,分数越高,对象越适合上下文
选择得分最高的对象。
注解
当没有单个对象的得分最高时,在开发模式中会引发一个异常,让您知道引擎无法识别要应用的视图。在生产模式下,此错误被消除,并选择得分最高的对象之一。
在这种情况下,您需要检查您的设计,并确保正确定义了选择器或AppObjects。这种错误通常是由于忘记改变 __regid__ 在派生类中,或者通过复制粘贴一些代码。
例如,如果您选择的是主 (__regid__ ='主要')视图 (__registry__ ='视图')对于包含 Card 实体,两个对象可能是可选的:
默认主视图 (`__select__ =是“instance(‘any’’)”,表示对象可用于任何类型的实体类型。
具体的 Card primary view (_ _选择“是”实例(“卡”),这意味着对象对于卡实体是可选的。
在这种情况下,其他特定于其他实体类型的主视图将不可选。在可选对象中, is_instance('Card') 选择器将返回更高的分数,因为它更具体,因此将按预期选择正确的视图。
2.1.4. 对象选择的API¶
这里是您将在每个注册表中获得的选择API。其中一些作为“etype”注册表,包含实体类,对其进行扩展。在这些方法中, *args, **kwargs 我们称之为 语境 .这些参数提供给选择器,选择器将检查其内容并相应返回分数。
select()
select_or_none()
possible_objects()
object_by_id()
2.2. 这个 AppObject 类¶
这个 cubicweb.appobject.AppObject
类是通过 cubicweb.cwvreg.CWRegistryStore
.
2.3. 谓词和选择器¶
谓词是由注册表调用的计分函数,用来告诉在给定上下文中何时可以选择AppObject。谓词可以使用运算符构建选择器链接在一起。选择器是将视图绑定到数据模型或任何输入上下文的粘合剂。适当地使用它们是构建行为良好的立方体的重要部分。
当然,随着需求的增长和对框架的熟悉,您可能需要编写自己的一组谓词(请参见 定义自己的谓词 )
谓词是测试上下文特定方面的类。选择器是通过组合现有谓词甚至选择器来构建的。
2.3.1. 使用和组合存在谓词¶
您可以使用 & , | 和 ~ 操作员。
当两个谓词使用 & 运算符,这意味着两者都应返回正分数。成功后,返回分数总和。
当两个谓词使用 | 操作员,这意味着其中一个应该返回正分数。如果成功,则返回第一个正数。
也可以在谓词前面加上 ~ 一元运算符。
当然,您可以使用括号来平衡表达式。
2.3.2. 例子¶
目标:在博客上,人们希望RSS链接指向博客条目,而不是博客实体本身。
为此,可以在实体类上定义一个方法,该方法返回给定实体的RSS流URL。上的默认实现 AnyEntity
(用作所有其他类的基础的通用实体类)和上的特定实现 Blog 会做我们想做的。
但是当我们有一个结果集包含 Blog 实体(或不同的实体),我们不知道在哪个实体上调用上述方法。在这种情况下,我们保留一般的行为。
因此,我们这里有两种情况,一种用于单个实体RSET,另一种用于多实体RSET。
在web/views/box.py中是rssiconbox类。看看它的选择器:
class RSSIconBox(box.Box):
''' just display the RSS icon on uniform result set '''
__select__ = box.Box.__select__ & non_final_entity()
考虑到:
继承的选择条件(必须在类层次结构中查找它们以了解详细信息)
non_final_entity
,它对包含非最终实体的结果集进行筛选(“最终实体”是实体属性类型的同义词,例如 String , Int 等)
这符合我们的第二种情况。因此,我们必须为第一种情况提供一个特定的组件:
class EntityRSSIconBox(RSSIconBox):
'''just display the RSS icon on uniform result set for a single entity'''
__select__ = RSSIconBox.__select__ & one_line_rset()
这里,有人补充说 one_line_rset
谓词,用于筛选大小为1的结果集。因此,在包含多个实体的结果集上, one_line_rset
使EntityRssiConBox类不可选。但是,对于具有一个实体的结果集, EntityRSSIconBox 班级的分数比 RSSIconBox 这就是我们想要的。
当然,完成后,您必须:
填写的调用方法 EntityRSSIconBox
提供返回RSS流URL的方法的默认实现
AnyEntity
在上重新定义此方法 Blog .
2.3.3. 何时使用选择器?¶
每当需要对结果集的形状或内容或任何其他上下文(请求表单参数中的值、经过身份验证的用户组等)进行分派时,都要使用选择器。几乎一直都是这样。
下面是一个简单的例子:
class UserLink(component.Component):
'''if the user is the anonymous user, build a link to login else a link
to the connected user object with a logout link
'''
__regid__ = 'loggeduserlink'
def call(self):
if self._cw.session.anonymous_session:
# display login link
...
else:
# display a link to the connected user object with a loggout link
...
用正确的方法来实现 CubicWeb 两个类有两个不同的类,它们共享相同的标识符,但具有不同的选择器,因此您将根据上下文获得正确的标识符。
class UserLink(component.Component):
'''display a link to the connected user object with a loggout link'''
__regid__ = 'loggeduserlink'
__select__ = component.Component.__select__ & authenticated_user()
def call(self):
# display useractions and siteactions
...
class AnonUserLink(component.Component):
'''build a link to login'''
__regid__ = 'loggeduserlink'
__select__ = component.Component.__select__ & anonymous_user()
def call(self):
# display login link
...
除了熟悉系统的可读性之外,最大的优点是通过改进组件化,您的多维数据集变得更容易定制。
2.3.4. 定义自己的谓词¶
你可以使用 objectify_predicate
decorator可以轻松地将自己的谓词编写为简单的python函数。
在其他情况下,您可以查看以下抽象基类:
ExpectedValuePredicate
EClassPredicate
EntityPredicate
2.3.5. 调试选择¶
偶尔,您需要了解为什么视图(或任何应用程序对象)被适当地选择或未被适当地选择。查看触发(或未触发)哪些谓词是方法。这个 traced_selection
上下文管理器来帮助实现这一点, 如果在调试模式下运行实例 .
2.4. 基本谓词¶
这里是对CubicWeb提供的一般谓词的描述,这些谓词应该适合您的大多数需求。
2.4.1. 裸谓词¶
这些谓词有点笨,这并不意味着它们(非常)有用。
yes
match_kwargs
appobject_selectable
adaptable
configuration_values
2.4.2. 结果集谓词¶
这些谓词正在上下文(“rset”参数或输入上下文)中查找结果集,并根据其形状匹配或不匹配。如果使用输入上下文的“row”和“col”参数指定结果集的特定单元格,则其中一些谓词具有不同的行为。
none_rset
any_rset
nonempty_rset
empty_rset
one_line_rset
multi_lines_rset
multi_columns_rset
paginated_rset
sorted_rset
one_etype_rset
multi_etypes_rset
2.4.3. 实体谓词¶
这些谓词正在查找 entity 输入上下文中的参数,或在结果集中找到的实体(“rset”参数或输入上下文),并根据实体(实例或类)属性匹配或不匹配。
non_final_entity
is_instance
score_entity
rql_condition
relation_possible
partial_relation_possible
has_related_entities
partial_has_related_entities
has_permission
has_add_permission
has_mimetype
is_in_state
on_fire_transition
2.4.4. 记录的用户谓词¶
这些谓词正在查找发出请求的用户的属性。
match_user_groups
2.4.5. Web请求谓词¶
这些谓词正在查找 web 请求,它们不能在数据存储库端使用。
no_cnx
anonymous_user
authenticated_user
match_form_params
match_search_state
match_context_prop
match_context
match_view
primary_view
contextual
specified_etype_implements
attribute_edited
match_transition
2.4.6. 其他谓词¶
match_exception
debug_mode
您还将发现一些其他(非常)特定的谓词隐藏在其他模块中,而不是 cubicweb.predicates
.