1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 |
|
4 Data as objects |
|
5 =============== |
|
6 |
|
7 In this chapter, we will introduce the objects that are used to handle |
|
8 the data stored in the database. |
|
9 |
|
10 Class `Entity` and `AnyEntity` |
|
11 ------------------------------ |
|
12 |
|
13 To provide a specific behavior for each entity, we have to define |
|
14 a class inheriting from `cubicweb.entities.AnyEntity`. In general, we |
|
15 define this class in a module of `mycube.entities` package of an application |
|
16 so that it will be available on both server and client side. |
|
17 |
|
18 The class `AnyEntity` is loaded dynamically from the class `Entity` |
|
19 (`cubciweb.common.entity`). We define a sub-class to add methods or to |
|
20 specialize the handling of a given entity type |
|
21 |
|
22 Descriptors are added when classes are registered in order to initialize the class |
|
23 according to its schema: |
|
24 |
|
25 * we can access the defined attributes in the schema thanks to the attributes of |
|
26 the same name on instances (typed value) |
|
27 |
|
28 * we can access the defined relations in the schema thanks to the relations of |
|
29 the same name on instances (entities instances list) |
|
30 |
|
31 The methods defined for `AnyEntity` or `Entity` are the following ones: |
|
32 |
|
33 * `has_eid()`, returns true is the entity has an definitive eid (e.g. not in the |
|
34 creation process) |
|
35 |
|
36 * `check_perm(action)`, checks if the user has the permission to execute the |
|
37 requested action on the entity |
|
38 |
|
39 :Formatting and output generation: |
|
40 |
|
41 * `view(vid, **kwargs)`, applies the given view to the entity |
|
42 |
|
43 * `absolute_url(**kwargs)`, returns an absolute URL to access the primary view |
|
44 of an entity |
|
45 |
|
46 * `rest_path()`, returns a relative REST URL to get the entity |
|
47 |
|
48 * `format(attr)`, returns the format (MIME type) of the field given un parameter |
|
49 |
|
50 * `printable_value(attr, value=_marker, attrtype=None, format='text/html')`, |
|
51 returns a string enabling the display of an attribute value in a given format |
|
52 (the value is automatically recovered if necessary) |
|
53 |
|
54 * `display_name(form='')`, returns a string to display the entity type by |
|
55 specifying the preferred form (`plural` for a plural form) |
|
56 |
|
57 :Data handling: |
|
58 |
|
59 * `as_rset()`, converts the entity into an equivalent result set simulating the |
|
60 request `Any X WHERE X eid _eid_` |
|
61 |
|
62 * `complete(skip_bytes=True)`, executes a request that recovers in one time |
|
63 all the missing attributes of an entity |
|
64 |
|
65 * `get_value(name)`, returns the value associated to the attribute name given |
|
66 in parameter |
|
67 |
|
68 * `related(rtype, x='subject', limit=None, entities=False)`, returns a list |
|
69 of entities related to the current entity by the relation given in parameter |
|
70 |
|
71 * `unrelated(rtype, targettype, x='subject', limit=None)`, returns a result set |
|
72 corresponding to the entities not related to the current entity by the |
|
73 relation given in parameter and satisfying its constraints |
|
74 |
|
75 * `set_attributes(**kwargs)`, updates the attributes list with the corresponding |
|
76 values given named parameters |
|
77 |
|
78 * `copy_relations(ceid)`, copies the relations of the entities having the eid |
|
79 given in the parameters on the current entity |
|
80 |
|
81 * `last_modified(view)`, returns the date the object has been modified |
|
82 (used by HTTP cache handling) |
|
83 |
|
84 * `delete()` allows to delete the entity |
|
85 |
|
86 :Standard meta-data (Dublin Core): |
|
87 |
|
88 * `dc_title()`, returns a unicode string corresponding to the meta-data |
|
89 `Title` (used by default the first attribute non-meta of the entity |
|
90 schema) |
|
91 |
|
92 * `dc_long_title()`, same as dc_title but can return a more |
|
93 detailled title |
|
94 |
|
95 * `dc_description(format='text/plain')`, returns a unicode string |
|
96 corresponding to the meta-data `Description` (look for a description |
|
97 attribute by default) |
|
98 |
|
99 * `dc_authors()`, returns a unicode string corresponding to the meta-data |
|
100 `Authors` (owners by default) |
|
101 |
|
102 * `dc_date(date_format=None)`, returns a unicode string corresponding to |
|
103 the meta-data `Date` (update date by default) |
|
104 |
|
105 :Vocabulary control on relations: |
|
106 |
|
107 * `vocabulary(rtype, x='subject', limit=None)`, called by the |
|
108 editing views, it returns a list of couples (label, eid) of entities |
|
109 that could be related to the entity by the relation `rtype` |
|
110 * `subject_relation_vocabulary(rtype, limit=None)`, called internally |
|
111 by `vocabulary` in the case of a subject relation |
|
112 * `object_relation_vocabulary(rtype, limit=None)`, called internally |
|
113 by `vocabulary` in the case of an object relation |
|
114 * `relation_vocabulary(rtype, targettype, x, limit=None)`, called |
|
115 internally by `subject_relation_vocabulary` and `object_relation_vocabulary` |
|
116 |
|
117 Class `TreeMixIn` |
|
118 ----------------- |
|
119 |
|
120 This class provides a tree interface. This mixin has to be inherited |
|
121 explicitly and configured using the tree_attribute, parent_target and |
|
122 children_target class attribute to benefit from this default implementation. |
|
123 |
|
124 This class provides the following methods: |
|
125 |
|
126 * `different_type_children(entities=True)`, returns children entities |
|
127 of different type as this entity. According to the `entities` parameter, |
|
128 returns entity objects (if entity=True) or the equivalent result set. |
|
129 |
|
130 * `same_type_children(entities=True)`, returns children entities of |
|
131 the same type as this entity. According to the `entities` parameter, |
|
132 return entity objects (if entity=True) or the equivalent result set. |
|
133 |
|
134 * `iterchildren( _done=None)`, iters on the children of the entity. |
|
135 |
|
136 * `prefixiter( _done=None)` |
|
137 |
|
138 * `path()`, returns the list of eids from the root object to this object. |
|
139 |
|
140 * `iterparents()`, iters on the parents of the entity. |
|
141 |
|
142 * `notification_references(view)`, used to control References field |
|
143 of email send on notification for this entity. `view` is the notification view. |
|
144 Should return a list of eids which can be used to generate message ids |
|
145 of previously sent email. |
|
146 |
|
147 `TreeMixIn` implements also the ITree interface (``cubicweb.interfaces``): |
|
148 |
|
149 * `parent()`, returns the parent entity if any, else None (e.g. if we are on the |
|
150 root) |
|
151 |
|
152 * `children(entities=True, sametype=False)`, returns children entities |
|
153 according to the `entities` parameter, return entity objects or the |
|
154 equivalent result set. |
|
155 |
|
156 * `children_rql()`, returns the RQL query corresponding to the children |
|
157 of the entity. |
|
158 |
|
159 * `is_leaf()`, returns True if the entity does not have any children. |
|
160 |
|
161 * `is_root()`, returns True if the entity does not have any parent. |
|
162 |
|
163 * `root()`, returns the root object of the tree representation of |
|
164 the entity and its related entities. |
|
165 |
|
166 Example of use |
|
167 `````````````` |
|
168 |
|
169 Imagine you defined three types of entities in your schema, and they |
|
170 relates to each others as follows in ``schema.py``:: |
|
171 |
|
172 class Entity1(EntityType): |
|
173 title = String() |
|
174 is_related_to = SubjectRelation('Entity2', 'subject') |
|
175 |
|
176 class Entity2(EntityType): |
|
177 title = String() |
|
178 belongs_to = SubjectRelation('Entity3', 'subject') |
|
179 |
|
180 class Entity3(EntityType): |
|
181 name = String() |
|
182 |
|
183 You would like to create a view that applies to both entity types |
|
184 `Entity1` and `Entity2` and which lists the entities they are related to. |
|
185 That means when you view `Entity1` you want to list all `Entity2`, and |
|
186 when you view `Entity2` you want to list all `Entity3`. |
|
187 |
|
188 In ``entities.py``:: |
|
189 |
|
190 class Entity1(TreeMixIn, AnyEntity): |
|
191 id = 'Entity1' |
|
192 __implements__ = AnyEntity.__implements__ + (ITree,) |
|
193 __rtags__ = {('is_related_to', 'Entity2', 'object'): 'link'} |
|
194 tree_attribute = 'is_related_to' |
|
195 |
|
196 def children(self, entities=True): |
|
197 return self.different_type_children(entities) |
|
198 |
|
199 class Entity2(TreeMixIn, AnyEntity): |
|
200 id = 'Entity2' |
|
201 __implements__ = AnyEntity.__implements__ + (ITree,) |
|
202 __rtags__ = {('belongs_to', 'Entity3', 'object'): 'link'} |
|
203 tree_attribute = 'belongs_to' |
|
204 |
|
205 def children(self, entities=True): |
|
206 return self.different_type_children(entities) |
|
207 |
|
208 Once this is done, you can define your common view as follows:: |
|
209 |
|
210 class E1E2CommonView(baseviews.PrimaryView): |
|
211 accepts = ('Entity11, 'Entity2') |
|
212 |
|
213 def render_entity_relations(self, entity, siderelations): |
|
214 self.wview('list', entity.children(entities=False)) |
|
215 |
|
216 |
|
217 *rtags* |
|
218 ------- |
|
219 |
|
220 *rtags* allow to specify certain behaviors of relations relative to a given |
|
221 entity type (see later). They are defined on the entity class by the attribute |
|
222 `rtags` which is a dictionary with as keys the triplets :: |
|
223 |
|
224 <relation type>, <target entity type>, <context position ("subject" ou "object")> |
|
225 |
|
226 and as values a `set` or a tuple of markers defining the properties that |
|
227 apply to this relation. |
|
228 |
|
229 It is possible to simplify this dictionary: |
|
230 |
|
231 * if we want to specifiy a single marker, it is not necessary to |
|
232 use a tuple as value, the marker by itself (character string) |
|
233 is enough |
|
234 * if we only care about a single type of relation and not about the target |
|
235 and the context position (or when this one is not ambigous), we can simply |
|
236 use the name of the relation type as key |
|
237 * if we want a marker to apply independently from the target entity type, |
|
238 we have to use the string `*` as target entity type |
|
239 |
|
240 |
|
241 Please note that this dictionary is *treated at the time the class is created*. |
|
242 It is automatically merged with the parent class(es) (no need to copy the |
|
243 dictionary from the parent class to modify it). Also, modifying it after the |
|
244 class is created will not have any effect... |
|
245 |
|
246 .. include:: B0031-define-entities.en.txt |
|
247 |
|