author | Aurelien Campeas <aurelien.campeas@logilab.fr> |
Wed, 14 Apr 2010 16:57:55 +0200 | |
branch | stable |
changeset 5258 | 9ff357e82e36 |
parent 5231 | 40f53867e332 |
child 5259 | 61505346e28f |
permissions | -rw-r--r-- |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
1 |
.. -*- coding: utf-8 -*- |
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
2 |
|
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
3 |
.. _hooks: |
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
4 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
5 |
Hooks and Operations |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
6 |
==================== |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
7 |
|
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
8 |
Generalities |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
9 |
------------ |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
10 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
11 |
Paraphrasing the `emacs`_ documentation, let us say that hooks are an |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
12 |
important mechanism for customizing an application. A hook is |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
13 |
basically a list of functions to be called on some well-defined |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
14 |
occasion (this is called `running the hook`). |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
15 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
16 |
.. _`emacs`: http://www.gnu.org/software/emacs/manual/html_node/emacs/Hooks.html |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
17 |
|
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
18 |
In CubicWeb, hooks are subclasses of the Hook class in |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
19 |
`server/hook.py`, implementing their own `call` method, and selected |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
20 |
over a set of pre-defined `events` (and possibly more conditions, |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
21 |
hooks being selectable AppObjects like views and components). |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
22 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
23 |
There are two families of events: data events and server events. In a |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
24 |
typical application, most of the Hooks are defined over data |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
25 |
events. |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
26 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
27 |
The purpose of data hooks is to complement the data model as defined |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
28 |
in the schema.py, which is static by nature, with dynamic or value |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
29 |
driven behaviours. It is functionally equivalent to a `database |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
30 |
trigger`_, except that database triggers definition languages are not |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
31 |
standardized, hence not portable (for instance, PL/SQL works with |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
32 |
Oracle and PostgreSQL but not SqlServer nor Sqlite). |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
33 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
34 |
.. _`database trigger`: http://en.wikipedia.org/wiki/Database_trigger |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
35 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
36 |
Data hooks can serve the following purposes: |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
37 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
38 |
* enforcing constraints that the static schema cannot express |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
39 |
(spanning several entities/relations, exotic value ranges and |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
40 |
cardinalities, etc.) |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
41 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
42 |
* implement computed attributes |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
43 |
|
5221
b851558456bb
[doc/book] remove merged chapter
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5220
diff
changeset
|
44 |
Operations are Hook-like objects that maye be created by Hooks and |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
45 |
scheduled to happen just before (or after) the `commit` event. Hooks |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
46 |
being fired immediately on data operations, it is sometime necessary |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
47 |
to delay the actual work down to a time where all other Hooks have |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
48 |
run, for instance a validation check which needs that all relations be |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
49 |
already set on an entity. Also while the order of execution of Hooks |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
50 |
is data dependant (and thus hard to predict), it is possible to force |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
51 |
an order on Operations. |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
52 |
|
5221
b851558456bb
[doc/book] remove merged chapter
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5220
diff
changeset
|
53 |
Operations also may be used to process various side effects associated |
b851558456bb
[doc/book] remove merged chapter
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5220
diff
changeset
|
54 |
with a transaction such as filesystem udpates, mail notifications, |
b851558456bb
[doc/book] remove merged chapter
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5220
diff
changeset
|
55 |
etc. |
b851558456bb
[doc/book] remove merged chapter
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5220
diff
changeset
|
56 |
|
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
57 |
Operations are subclasses of the Operation class in `server/hook.py`, |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
58 |
implementing `precommit_event` and other standard methods (wholly |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
59 |
described later in this chapter). |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
60 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
61 |
Events |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
62 |
------ |
2172
cf8f9180e63e
delete-trailing-whitespace
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
1714
diff
changeset
|
63 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
64 |
Hooks are mostly defined and used to handle `dataflow`_ operations. It |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
65 |
means as data gets in (entities added, updated, relations set or |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
66 |
unset), specific events are issued and the Hooks matching these events |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
67 |
are called. |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
68 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
69 |
.. _`dataflow`: http://en.wikipedia.org/wiki/Dataflow |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
70 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
71 |
Below comes a list of the dataflow events related to entities operations: |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
72 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
73 |
* before_add_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
74 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
75 |
* before_update_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
76 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
77 |
* before_delete_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
78 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
79 |
* after_add_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
80 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
81 |
* after_update_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
82 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
83 |
* after_delete_entity |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
84 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
85 |
These define ENTTIES HOOKS. RELATIONS HOOKS are defined |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
86 |
over the following events: |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
87 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
88 |
* after_add_relation |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
89 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
90 |
* after_delete_relation |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
91 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
92 |
* before_add_relation |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
93 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
94 |
* before_delete_relation |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
95 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
96 |
This is an occasion to remind us that relations support the add/delete |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
97 |
operation, but no update. |
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
98 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
99 |
Non data events also exist. These are called SYSTEM HOOKS. |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
100 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
101 |
* server_startup |
2172
cf8f9180e63e
delete-trailing-whitespace
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
1714
diff
changeset
|
102 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
103 |
* server_shutdown |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
104 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
105 |
* server_maintenance |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
106 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
107 |
* server_backup |
2172
cf8f9180e63e
delete-trailing-whitespace
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents:
1714
diff
changeset
|
108 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
109 |
* server_restore |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
110 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
111 |
* session_open |
1714
a721966779be
new book layout, do not compile yet
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
112 |
|
5191
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
113 |
* session_close |
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
114 |
|
6d182c7d4392
[doc/book] begin chapter on Hooks/Operations
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
2172
diff
changeset
|
115 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
116 |
Using dataflow Hooks |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
117 |
-------------------- |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
118 |
|
5231
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
119 |
Dataflow hooks either automate data operations or maintain the |
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
120 |
consistency of the data model. In the later case, we must use a |
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
121 |
specific exception named ValidationError |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
122 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
123 |
Validation Errors |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
124 |
~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
125 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
126 |
When a condition is not met in a Hook/Operation, it must raise a |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
127 |
`ValidationError`. Raising anything but a (subclass of) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
128 |
ValidationError is a programming error. Raising a ValidationError |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
129 |
entails aborting the current transaction. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
130 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
131 |
The ValidationError exception is used to convey enough information up |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
132 |
to the user interface. Hence its constructor is different from the |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
133 |
default Exception constructor. It accepts, positionally: |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
134 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
135 |
* an entity eid, |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
136 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
137 |
* a dict whose keys represent attribute (or relation) names and values |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
138 |
an end-user facing message (hence properly translated) relating the |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
139 |
problem. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
140 |
|
5231
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
141 |
An entity hook |
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
142 |
~~~~~~~~~~~~~~ |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
143 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
144 |
We will use a very simple example to show hooks usage. Let us start |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
145 |
with the following schema. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
146 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
147 |
.. sourcecode:: python |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
148 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
149 |
class Person(EntityType): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
150 |
age = Int(required=True) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
151 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
152 |
We would like to add a range constraint over a person's age. Let's |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
153 |
write an hook. It shall be placed into mycube/hooks.py. If this file |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
154 |
were to grow too much, we can easily have a mycube/hooks/... package |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
155 |
containing hooks in various modules. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
156 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
157 |
.. sourcecode:: python |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
158 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
159 |
from cubicweb import ValidationError |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
160 |
from cubicweb.selectors import implements |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
161 |
from cubicweb.server.hook import Hook |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
162 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
163 |
class PersonAgeRange(Hook): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
164 |
__regid__ = 'person_age_range' |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
165 |
events = ('before_add_entity', 'before_update_entity') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
166 |
__select__ = Hook.__select__ & implements('Person') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
167 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
168 |
def __call__(self): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
169 |
if 0 >= self.entity.age <= 120: |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
170 |
return |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
171 |
msg = self._cw._('age must be between 0 and 120') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
172 |
raise ValidationError(self.entity.eid, {'age': msg}) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
173 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
174 |
Hooks being AppObjects like views, they have a __regid__ and a |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
175 |
__select__ class attribute. The base __select__ is augmented with an |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
176 |
`implements` selector matching the desired entity type. The `events` |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
177 |
tuple is used by the Hook.__select__ base selector to dispatch the |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
178 |
hook on the right events. In an entity hook, it is possible to |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
179 |
dispatch on any entity event (e.g. 'before_add_entity', |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
180 |
'before_update_entity') at once if needed. |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
181 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
182 |
Like all appobjects, hooks have the `self._cw` attribute which |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
183 |
represents the current session. In entity hooks, a `self.entity` |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
184 |
attribute is also present. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
185 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
186 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
187 |
A relation hook |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
188 |
~~~~~~~~~~~~~~~ |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
189 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
190 |
Let us add another entity type with a relation to person (in |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
191 |
mycube/schema.py). |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
192 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
193 |
.. sourcecode:: python |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
194 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
195 |
class Company(EntityType): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
196 |
name = String(required=True) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
197 |
boss = SubjectRelation('Person', cardinality='1*') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
198 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
199 |
We would like to constrain the company's bosses to have a minimum |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
200 |
(legal) age. Let's write an hook for this, which will be fired when |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
201 |
the `boss` relation is established. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
202 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
203 |
.. sourcecode:: python |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
204 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
205 |
class CompanyBossLegalAge(Hook): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
206 |
__regid__ = 'company_boss_legal_age' |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
207 |
events = ('before_add_relation',) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
208 |
__select__ = Hook.__select__ & match_rtype('boss') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
209 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
210 |
def __call__(self): |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
211 |
boss = self._cw.entity_from_eid(self.eidto) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
212 |
if boss.age < 18: |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
213 |
msg = self._cw._('the minimum age for a boss is 18') |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
214 |
raise ValidationError(self.eidfrom, {'boss': msg}) |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
215 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
216 |
We use the `match_rtype` selector to select the proper relation type. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
217 |
|
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
218 |
The essential difference with respect to an entity hook is that there |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
219 |
is no self.entity, but `self.eidfrom` and `self.eidto` hook attributes |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
220 |
which represent the subject and object eid of the relation. |
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
221 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
222 |
Using Operations |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
223 |
---------------- |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
224 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
225 |
Let's augment our example with a new `subsidiary_of` relation on Company. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
226 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
227 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
228 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
229 |
class Company(EntityType): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
230 |
name = String(required=True) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
231 |
boss = SubjectRelation('Person', cardinality='1*') |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
232 |
subsidiary_of = SubjectRelation('Company', cardinality='*?') |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
233 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
234 |
Base example |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
235 |
~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
236 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
237 |
We would like to check that there is no cycle by the `subsidiary_of` |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
238 |
relation. This is best achieved in an Operation since all relations |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
239 |
are likely to be set at commit time. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
240 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
241 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
242 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
243 |
def check_cycle(self, session, eid, rtype, role='subject'): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
244 |
parents = set([eid]) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
245 |
parent = session.entity_from_eid(eid) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
246 |
while parent.related(rtype, role): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
247 |
parent = parent.related(rtype, role)[0] |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
248 |
if parent.eid in parents: |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
249 |
msg = session._('detected %s cycle' % rtype) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
250 |
raise ValidationError(eid, {rtype: msg}) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
251 |
parents.add(parent.eid) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
252 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
253 |
class CheckSubsidiaryCycleOp(Operation): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
254 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
255 |
def precommit_event(self): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
256 |
check_cycle(self.session, self.eidto, 'subsidiary_of') |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
257 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
258 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
259 |
class CheckSubsidiaryCycleHook(Hook): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
260 |
__regid__ = 'check_no_subsidiary_cycle' |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
261 |
events = ('after_add_relation',) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
262 |
__select__ = Hook.__select__ & match_rtype('subsidiary_of') |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
263 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
264 |
def __call__(self): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
265 |
CheckSubsidiaryCycleOp(self._cw, eidto=self.eidto) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
266 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
267 |
The operation is instantiated in the Hook.__call__ method. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
268 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
269 |
An operation always takes a session object as first argument |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
270 |
(accessible as `.session` from the operation instance), and optionally |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
271 |
all keyword arguments needed by the operation. These keyword arguments |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
272 |
will be accessible as attributes from the operation instance. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
273 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
274 |
Like in Hooks, ValidationError can be raised in Operations. Other |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
275 |
exceptions are programming errors. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
276 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
277 |
Notice how our hook will instantiate an operation each time the Hook |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
278 |
is called, i.e. each time the `subsidiary_of` relation is set. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
279 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
280 |
Using set_operation |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
281 |
~~~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
282 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
283 |
There is an alternative method to schedule an Operation from a Hook, |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
284 |
using the `set_operation` function. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
285 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
286 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
287 |
|
5231
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
288 |
from cubicweb.server.hook import set_operation |
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
289 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
290 |
class CheckSubsidiaryCycleHook(Hook): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
291 |
__regid__ = 'check_no_subsidiary_cycle' |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
292 |
events = ('after_add_relation',) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
293 |
__select__ = Hook.__select__ & match_rtype('subsidiary_of') |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
294 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
295 |
def __call__(self): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
296 |
set_operation(self._cw, 'subsidiary_cycle_detection', self.eidto, |
5231
40f53867e332
[doc/book] misc fixes/enhancements & notes
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5221
diff
changeset
|
297 |
CheckSubsidiaryCycleOp, rtype=self.rtype) |
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
298 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
299 |
class CheckSubsidiaryCycleOp(Operation): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
300 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
301 |
def precommit_event(self): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
302 |
for eid in self._cw.transaction_data['subsidiary_cycle_detection']: |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
303 |
check_cycle(self.session, eid, self.rtype) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
304 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
305 |
Here, we call set_operation with a session object, a specially forged |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
306 |
key, a value that is the actual payload of an individual operation (in |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
307 |
our case, the object of the subsidiary_of relation) , the class of the |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
308 |
Operation, and more optional parameters to give to the operation (here |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
309 |
the rtype which do not vary accross operations). |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
310 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
311 |
The body of the operation must then iterate over the values that have |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
312 |
been mapped in the transaction_data dictionary to the forged key. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
313 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
314 |
This mechanism is especially useful on two occasions (not shown in our |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
315 |
example): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
316 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
317 |
* massive data import (reduced memory consumption within a large |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
318 |
transaction) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
319 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
320 |
* when several hooks need to instantiate the same operation (e.g. an |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
321 |
entity and a relation hook). |
5202
4a77da652759
[doc/book] more about hooks (simple examples with entities and relations)
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5191
diff
changeset
|
322 |
|
5220
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
323 |
Operation: a small API overview |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
324 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
325 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
326 |
.. autoclass:: cubicweb.server.hook.Operation |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
327 |
.. autoclass:: cubicweb.server.hook.LateOperation |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
328 |
.. autofunction:: cubicweb.server.hook.set_operation |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
329 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
330 |
Hooks writing rules |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
331 |
------------------- |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
332 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
333 |
Remainder |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
334 |
~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
335 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
336 |
Never, ever use the `entity.foo = 42` notation to update an entity. It |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
337 |
will not work. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
338 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
339 |
How to choose between a before and an after event ? |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
340 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
341 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
342 |
Before hooks give you access to the old attribute (or relation) |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
343 |
values. By definition the database is not yet updated in a before |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
344 |
hook. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
345 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
346 |
To access old and new values in an before_update_entity hook, one can |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
347 |
use the `server.hook.entity_oldnewvalue` function which returns a |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
348 |
tuple of the old and new values. This function takes an entity and an |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
349 |
attribute name as parameters. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
350 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
351 |
In a 'before_add|update_entity' hook the self.entity contains the new |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
352 |
values. One is allowed to further modify them before database |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
353 |
operations, using the dictionary notation. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
354 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
355 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
356 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
357 |
self.entity['age'] = 42 |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
358 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
359 |
This is because using self.entity.set_attributes(age=42) will |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
360 |
immediately update the database (which does not make sense in a |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
361 |
pre-database hook), and will trigger any existing |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
362 |
before_add|update_entity hook, thus leading to infinite hook loops or |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
363 |
such awkward situations. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
364 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
365 |
Beyond these specific cases, updating an entity attribute or relation |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
366 |
must *always* be done using `set_attributes` and `set_relations` |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
367 |
methods. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
368 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
369 |
(Of course, ValidationError will always abort the current transaction, |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
370 |
whetever the event). |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
371 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
372 |
Peculiarities of inlined relations |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
373 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
374 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
375 |
Some relations are defined in the schema as `inlined` (see |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
376 |
:ref:`RelationType` for details). In this case, they are inserted in |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
377 |
the database at the same time as entity attributes. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
378 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
379 |
Hence in the case of before_add_relation, such relations already exist |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
380 |
in the database. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
381 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
382 |
Edited attributes |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
383 |
~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
384 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
385 |
On udpates, it is possible to ask the `entity.edited_attributes` |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
386 |
variable whether one attribute has been updated. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
387 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
388 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
389 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
390 |
if 'age' not in entity.edited_attribute: |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
391 |
return |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
392 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
393 |
Deleted in transaction |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
394 |
~~~~~~~~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
395 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
396 |
The session object has a deleted_in_transaction method, which can help |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
397 |
writing deletion Hooks. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
398 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
399 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
400 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
401 |
if self._cw.deleted_in_transaction(self.eidto): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
402 |
return |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
403 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
404 |
Given this predicate, we can avoid scheduling an operation. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
405 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
406 |
Disabling hooks |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
407 |
~~~~~~~~~~~~~~~ |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
408 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
409 |
It is sometimes convenient to disable some hooks. For instance to |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
410 |
avoid infinite Hook loops. One uses the `hooks_control` context |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
411 |
manager. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
412 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
413 |
This can be controlled more finely through the `category` Hook class |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
414 |
attribute. |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
415 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
416 |
.. sourcecode:: python |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
417 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
418 |
with hooks_control(self.session, self.session.HOOKS_ALLOW_ALL, <category>): |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
419 |
# ... do stuff |
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
420 |
|
42f854b6083d
[doc/book] complete chapter on hooks & ops
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
5202
diff
changeset
|
421 |
.. autoclass:: cubicweb.server.session.hooks_control |