3 Yams *schema* |
3 Yams *schema* |
4 ------------- |
4 ------------- |
5 |
5 |
6 The **schema** is the core piece of a *CubicWeb* instance as it defines |
6 The **schema** is the core piece of a *CubicWeb* instance as it defines |
7 the handled data model. It is based on entity types that are either already |
7 the handled data model. It is based on entity types that are either already |
8 defined in the *CubicWeb* standard library; or more specific types, that |
8 defined in the *CubicWeb* standard library; or more specific types defined |
9 *CubicWeb* expects to find in one or more Python files under the directory |
9 in cubes. The schema for a cube is defined in a :file:schema.py file or in |
10 `schema`. |
10 one or more Python files under the :file:`schema` directory (python package). |
11 |
11 |
12 At this point, it is important to make clear the difference between |
12 At this point, it is important to make clear the difference between |
13 *relation type* and *relation definition*: a *relation type* is only a relation |
13 *relation type* and *relation definition*: a *relation type* is only a relation |
14 name with potentially other additionnal properties (see XXXX), whereas a |
14 name with potentially other additionnal properties (see below), whereas a |
15 *relation definition* is a complete triplet |
15 *relation definition* is a complete triplet |
16 "<subject entity type> <relation type> <object entity type>". |
16 "<subject entity type> <relation type> <object entity type>". |
17 A relation type could have been implied if none is related to a |
17 A relation type could have been implied if none is related to a |
18 relation definition of the schema. |
18 relation definition of the schema. |
19 |
19 |
20 |
20 Also, it should be clear that to properly handle data migration, an instance'schema |
21 All *CubicWeb* built-in types are available : `String`, `Int`, `Float`, |
21 is stored in the database, so the python schema file used to defined it are only readen |
|
22 when the instance is created or upgraded. |
|
23 |
|
24 The following built-in types are available : `String`, `Int`, `Float`, |
22 `Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte` |
25 `Decimal`, `Boolean`, `Date`, `Datetime`, `Time`, `Interval`, `Byte` |
23 and `Password`. |
26 and `Password`. |
24 They are implicitely imported (as well as the special the function "_" |
27 |
25 for translation :ref:`internationalization`). |
28 You'll also have access to :ref:`CWBaseEntityTypes_:base cubicweb entitye types`. |
26 |
29 |
27 The instance schema is defined on all appobjects by a .schema class attribute set |
30 The instance schema is accessible through the .schema attribute of the |
28 on registration. It's an instance of :class:`yams.schema.Schema`. |
31 `vregistry`. It's an instance of :class:`cubicweb.schema.Schema`, which |
|
32 extends :class:`yams.schema.Schema`. |
|
33 |
|
34 :note: |
|
35 In previous yams versions, almost all classes where available without |
|
36 any import, but the should now be explicitely imported. |
|
37 |
29 |
38 |
30 Entity type |
39 Entity type |
31 ~~~~~~~~~~~ |
40 ~~~~~~~~~~~ |
32 It's an instance of :class:`yams.schema.EntitySchema` |
41 It's an instance of :class:`yams.schema.EntitySchema`. Each entity types has |
33 |
42 a set of attributes and relation and some permissions, defining who can add, read, |
34 XXX meta |
43 update or delete entities of this type. |
35 XXX permission |
44 |
36 XXX yams inheritance |
45 XXX yams inheritance |
37 |
46 |
38 Relation type |
47 Relation type |
39 ~~~~~~~~~~~~~ |
48 ~~~~~~~~~~~~~ |
40 It's an instance of :class:`yams.schema.RelationSchema` |
49 It's an instance of :class:`yams.schema.RelationSchema`. A relation type is simply |
41 |
50 a semantic definition of a kind of relationship that may occurs in your application. |
42 In addition to the permissions, the properties of the relation types |
51 |
43 (shared also by all definition of relation of this type) are : |
52 It's important to choose a good name, at least to avoid conflicts with some semantically |
44 |
53 different relation defined in other cubes (since we've no namespace yet). |
|
54 |
|
55 A relation type hold the following properties (which are hence shared between all |
|
56 relation definitions of that type): |
45 |
57 |
46 * `inlined` : boolean handling the physical optimization for archiving |
58 * `inlined` : boolean handling the physical optimization for archiving |
47 the relation in the subject entity table, instead of creating a specific |
59 the relation in the subject entity table, instead of creating a specific |
48 table for the relation. This applies to the relation when the cardinality |
60 table for the relation. This applies to relations where cardinality |
49 of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) |
61 of subject->relation->object is 0..1 (`?`) or 1..1 (`1`) for *all* its relation |
|
62 definitions. |
50 |
63 |
51 * `symmetric` : boolean indicating that the relation is symmetrical, which |
64 * `symmetric` : boolean indicating that the relation is symmetrical, which |
52 means `X relation Y` implies `Y relation X` |
65 means that `X relation Y` implies `Y relation X`. |
53 |
|
54 XXX meta |
|
55 XXX permission |
|
56 |
66 |
57 |
67 |
58 Relation definition |
68 Relation definition |
59 ~~~~~~~~~~~~~~~~~~~ |
69 ~~~~~~~~~~~~~~~~~~~ |
60 Relation definition are represented in yams using an internal structure only exposed through the :mod:`api <yams.schema>`. |
70 It's an instance of :class:`yams.schema.RelationDefinition`. It is a complete triplet |
|
71 "<subject entity type> <relation type> <object entity type>". |
61 |
72 |
62 Properties |
73 Properties |
63 `````````` |
74 `````````` |
64 Properties defined below are accessible through the following api: |
|
65 |
|
66 RelationSchema.rproperties() |
|
67 RelationSchema.rproperty(subjtype, objtype, property name) |
|
68 |
75 |
69 * Optional properties for attributes and relations : |
76 * Optional properties for attributes and relations : |
70 |
77 |
71 - `description` : a string describing an attribute or a relation. By default |
78 - `description` : a string describing an attribute or a relation. By default |
72 this string will be used in the editing form of the entity, which means |
79 this string will be used in the editing form of the entity, which means |
104 attribute. |
106 attribute. |
105 |
107 |
106 - `default` : default value of the attribute. In case of date types, the values |
108 - `default` : default value of the attribute. In case of date types, the values |
107 which could be used correspond to the RQL keywords `TODAY` and `NOW`. |
109 which could be used correspond to the RQL keywords `TODAY` and `NOW`. |
108 |
110 |
109 - `vocabulary` : specify static possible values of an attribute |
|
110 |
|
111 * optional properties of type `String` : |
111 * optional properties of type `String` : |
112 |
112 |
113 - `fulltextindexed` : boolean indicating if the attribute is part of |
113 - `fulltextindexed` : boolean indicating if the attribute is part of |
114 the full text index (false by default) (*applicable on the type `Byte` |
114 the full text index (false by default) (*applicable on the type `Byte` |
115 as well*) |
115 as well*) |
116 |
116 |
117 - `internationalizable` : boolean indicating if the value of the attribute |
117 - `internationalizable` : boolean indicating if the value of the attribute |
118 is internationalizable (false by default) |
118 is internationalizable (false by default) |
119 |
|
120 - `maxsize` : integer providing the maximum size of the string (no limit by default) |
|
121 |
119 |
122 * optional properties for relations : |
120 * optional properties for relations : |
123 |
121 |
124 - `composite` : string indicating that the subject (composite == 'subject') |
122 - `composite` : string indicating that the subject (composite == 'subject') |
125 is composed of the objects of the relations. For the opposite case (when |
123 is composed of the objects of the relations. For the opposite case (when |
126 the object is composed of the subjects of the relation), we just set |
124 the object is composed of the subjects of the relation), we just set |
127 'object' as value. The composition implies that when the relation |
125 'object' as value. The composition implies that when the relation |
128 is deleted (so when the composite is deleted), the composed are also deleted. |
126 is deleted (so when the composite is deleted, at least), the composed are also deleted. |
129 |
127 |
130 - `fti_container`: XXX feed me |
128 - `fti_container`: XXX feed me |
131 |
129 |
132 Constraints |
130 Constraints |
133 ``````````` |
131 ``````````` |
346 The class definition contains the description of attributes and relations |
346 The class definition contains the description of attributes and relations |
347 for the defined entity type. |
347 for the defined entity type. |
348 The class name corresponds to the entity type name. It is exepected to be |
348 The class name corresponds to the entity type name. It is exepected to be |
349 defined in the module ``mycube.schema``. |
349 defined in the module ``mycube.schema``. |
350 |
350 |
351 |
351 When defining a schema using python files, you may use the following shortcuts: |
352 For example :: |
352 |
|
353 - ._cwuired` : boolean indicating if the attribute is._cwuired, eg subject cardinality is '1' |
|
354 |
|
355 - `vocabulary` : specify static possible values of an attribute |
|
356 |
|
357 - `maxsize` : integer providing the maximum size of a string (no limit by default) |
|
358 |
|
359 For example: |
|
360 |
|
361 .. sourcecode:: python |
353 |
362 |
354 class Person(EntityType): |
363 class Person(EntityType): |
355 """A person with the properties and the relations necessary for my |
364 """A person with the properties and the relations necessary for my |
356 application""" |
365 application""" |
357 |
366 |
358 last_name = String(required=True, fulltextindexed=True) |
367 last_name = String._cwuired=True, fulltextindexed=True) |
359 first_name = String(required=True, fulltextindexed=True) |
368 first_name = String._cwuired=True, fulltextindexed=True) |
360 title = String(vocabulary=('Mr', 'Mrs', 'Miss')) |
369 title = String(vocabulary=('Mr', 'Mrs', 'Miss')) |
361 date_of_birth = Date() |
370 date_of_birth = Date() |
362 works_for = SubjectRelation('Company', cardinality='?*') |
371 works_for = SubjectRelation('Company', cardinality='?*') |
363 |
372 |
364 |
373 |
427 |
436 |
428 In the case of simultaneous relations definitions, `subject` and `object` |
437 In the case of simultaneous relations definitions, `subject` and `object` |
429 can both be equal to the value of the first argument of `SubjectRelation` |
438 can both be equal to the value of the first argument of `SubjectRelation` |
430 and `ObjectRelation`. |
439 and `ObjectRelation`. |
431 |
440 |
432 When a relation is not inlined and not symmetrical, and it does not require |
441 When a relation is not inlined and not symmetrical, and it does not._cwuire |
433 specific permissions, its definition (by using `SubjectRelation` and |
442 specific permissions, its definition (by using `SubjectRelation` and |
434 `ObjectRelation`) is all we need. |
443 `ObjectRelation`) is all we need. |
435 |
444 |
436 |
445 |
437 Definition of permissions |
446 Definition of permissions |
438 ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
447 ~~~~~~~~~~~~~~~~~~~~~~~~~~ |
439 |
448 |
440 In addition to that the entity type `CWPermission` from the standard library |
449 In addition to that the entity type `CWPermission` from the standard library |
441 allow to build very complex and dynamic security architecture. The schema of |
450 allow to build very complex and dynamic security architecture. The schema of |
442 this entity type is as follow : :: |
451 this entity type is as follow: |
443 |
452 |
444 class CWPermission(MetaEntityType): |
453 .. sourcecode:: python |
|
454 |
|
455 class CWPermission(EntityType): |
445 """entity type that may be used to construct some advanced security configuration |
456 """entity type that may be used to construct some advanced security configuration |
446 """ |
457 """ |
447 name = String(required=True, indexed=True, internationalizable=True, maxsize=100) |
458 name = String._cwuired=True, indexed=True, internationalizable=True, maxsize=100) |
448 require_group = SubjectRelation('CWGroup', cardinality='+*', |
459 ._cwuire_group = SubjectRelation('CWGroup', cardinality='+*', |
449 description=_('groups to which the permission is granted')) |
460 description=_('groups to which the permission is granted')) |
450 require_state = SubjectRelation('State', |
461 ._cwuire_state = SubjectRelation('State', |
451 description=_("entity's state in which the permission is applicable")) |
462 description=_("entity's state in which the permission is applicable")) |
452 # can be used on any entity |
463 # can be used on any entity |
453 require_permission = ObjectRelation('**', cardinality='*1', composite='subject', |
464 ._cwuire_permission = ObjectRelation('**', cardinality='*1', composite='subject', |
454 description=_("link a permission to the entity. This " |
465 description=_("link a permission to the entity. This " |
455 "permission should be used in the security " |
466 "permission should be used in the security " |
456 "definition of the entity's type to be useful.")) |
467 "definition of the entity's type to be useful.")) |
457 |
468 |
458 |
469 |
459 Example of configuration :: |
470 Example of configuration: |
|
471 |
|
472 .. sourcecode:: python |
460 |
473 |
461 |
474 |
462 ... |
475 ... |
463 |
476 |
464 class Version(EntityType): |
477 class Version(EntityType): |
465 """a version is defining the content of a particular project's release""" |
478 """a version is defining the content of a particular project's release""" |
466 |
479 |
467 permissions = {'read': ('managers', 'users', 'guests',), |
480 __permissions__ = {'read': ('managers', 'users', 'guests',), |
468 'update': ('managers', 'logilab', 'owners',), |
481 'update': ('managers', 'logilab', 'owners',), |
469 'delete': ('managers', ), |
482 'delete': ('managers', ), |
470 'add': ('managers', 'logilab', |
483 'add': ('managers', 'logilab', |
471 ERQLExpression('X version_of PROJ, U in_group G,' |
484 ERQLExpression('X version_of PROJ, U in_group G,' |
472 'PROJ require_permission P, P name "add_version",' |
485 'PROJ._cwuire_permission P, P name "add_version",' |
473 'P require_group G'),)} |
486 'P._cwuire_group G'),)} |
474 |
487 |
475 ... |
|
476 |
488 |
477 class version_of(RelationType): |
489 class version_of(RelationType): |
478 """link a version to its project. A version is necessarily linked to one and only one project. |
490 """link a version to its project. A version is necessarily linked to one and only one project. |
479 """ |
491 """ |
480 permissions = {'read': ('managers', 'users', 'guests',), |
492 __permissions__ = {'read': ('managers', 'users', 'guests',), |
481 'delete': ('managers', ), |
493 'delete': ('managers', ), |
482 'add': ('managers', 'logilab', |
494 'add': ('managers', 'logilab', |
483 RRQLExpression('O require_permission P, P name "add_version",' |
495 RRQLExpression('O._cwuire_permission P, P name "add_version",' |
484 'U in_group G, P require_group G'),) |
496 'U in_group G, P._cwuire_group G'),) |
485 } |
497 } |
486 inlined = True |
498 inlined = True |
487 |
499 |
488 This configuration indicates that an entity `CWPermission` named |
500 This configuration indicates that an entity `CWPermission` named |
489 "add_version" can be associated to a project and provides rights to create |
501 "add_version" can be associated to a project and provides rights to create |