Skip to content

Commit dcdd699

Browse files
committed
Tidy event-handlers.md
1 parent aadcec3 commit dcdd699

File tree

1 file changed

+44
-53
lines changed

1 file changed

+44
-53
lines changed
Lines changed: 44 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,101 @@
11
---
22
myst:
33
html_meta:
4-
"description": ""
5-
"property=og:description": ""
6-
"property=og:title": ""
7-
"keywords": ""
4+
"description": "How to add custom event handlers for your content types"
5+
"property=og:description": "How to add custom event handlers for your content types"
6+
"property=og:title": "How to add custom event handlers for your content types"
7+
"keywords": "Plone, content types, event handlers"
88
---
99

1010
# Event handlers
1111

12-
**Adding custom event handlers for your type**
12+
This chapter describes how to add custom event handlers for your type.
1313

1414
Zope (and so Plone) has a powerful event notification and subscriber subsystem.
1515
Events notifications are already fired at several places.
1616

17-
With custom subscribers to these events more dynamic functionality can be added.
17+
With custom subscribers to these events, more dynamic functionality can be added.
1818
It is possible to react when something happens to objects of a specific type.
1919

20-
Zopes event model is *synchronous*.
21-
When an event is broadcast (via the `notify()` function from the [zope.event] package) all registered event handlers will be called.
22-
This happens for example from the `save` action of an add form, on move or delete of content-objects.
23-
There is no guarantee of which order the event handlers will be called in, however.
20+
Zope's event model is *synchronous*.
21+
When an event is broadcast (via the `notify()` function from the [`zope.event`](https://pypi.org/project/zope.event/) package), all registered event handlers will be called.
22+
This happens, for example, from the `save` action of an add form, or on move or delete of content objects.
23+
There is no guarantee in which order the event handlers will be called.
2424

2525
Each event is described by an interface, and will typically carry some information about the event.
2626
Some events are known as *object events*, and provide `zope.component.interfaces.IObjectEvent`.
27-
These have an `object` attribute giving access to the (content) object that the event relates to.
27+
These have an `object` attribute giving access to the content object that the event relates to.
2828
Object events allow event handlers to be registered for a specific type of object as well as a specific type of event.
2929

3030
Some of the most commonly used event types in Plone are shown below.
3131
They are all object events.
3232

3333
`zope.lifecycleevent.interfaces.IObjectCreatedEvent`
34-
35-
: fired by the standard add form just after an object has been created, but before it has been added on the container.
36-
Note that it is often easier to write a handler for `IObjectAddedEvent` (see below), because at this point the object has a proper acquisition context.
34+
: Fired by the standard add form just after an object has been created, but before it has been added on the container.
35+
Note that it is often easier to write a handler for `IObjectAddedEvent` (see below), because at this point the object has a proper acquisition context.
3736

3837
`zope.lifecycleevent.interfaces.IObjectAddedEvent`
39-
40-
: fired when an object has been added to its container.
41-
The container is available as the `newParent` attribute.
42-
The name the new item holds in the container is available as `newName`.
38+
: Fired when an object has been added to its container.
39+
The container is available as the `newParent` attribute.
40+
The name the new item holds in the container is available as `newName`.
4341

4442
`OFS.interfaces.IObjectWillBeAddedEvent`
45-
46-
: fired before an object is added to its container.
47-
It is also fired on move of an object (copy/paste).
43+
: Fired before an object is added to its container.
44+
It is also fired on move of an object (copy/paste).
4845

4946
`zope.lifecycleevent.interfaces.IObjectModifiedEvent`
50-
51-
: fired by the standard edit form when an object has been modified.
47+
: Fired by the standard edit form when an object has been modified.
5248

5349
`zope.lifecycleevent.interfaces.IObjectRemovedEvent`
54-
55-
: fired when an object has been removed from its container.
56-
The container is available as the `oldParent` attribute.
57-
The name the item held in the container is available as `oldName`.
50+
: Fired when an object has been removed from its container.
51+
The container is available as the `oldParent` attribute.
52+
The name the item held in the container is available as `oldName`.
5853

5954
`OFS.interfaces.IObjectWillBeRemovedEvent`
60-
61-
: fired before an object is removed. Until here no deletion has happend.
62-
It is also fired on move of an object (copy/paste).
55+
: Fired before an object is removed.
56+
Until here, no deletion has happend.
57+
It is also fired on move of an object (copy/paste).
6358

6459
`zope.lifecycleevent.interfaces.IObjectMovedEvent`
65-
66-
: fired when an object is added to, removed from, renamed in, or moved between containers.
67-
This event is a super-type of `IObjectAddedEvent` and `IObjectRemovedEvent`, shown above.
68-
An event handler registered for this interface will be invoked for the ‘added’ and ‘removed’ cases as well.
69-
When an object is moved or renamed, all of `oldParent`, `newParent`, `oldName` and `newName` will be set.
60+
: Fired when an object is added to, removed from, renamed in, or moved between containers.
61+
This event is a super-type of `IObjectAddedEvent` and `IObjectRemovedEvent`, shown above.
62+
An event handler registered for this interface will be invoked for the "added" and "removed" cases as well.
63+
When an object is moved or renamed, all of `oldParent`, `newParent`, `oldName`, and `newName` will be set.
7064

7165
`Products.CMFCore.interfaces.IActionSucceededEvent`
72-
73-
: fired when a workflow event has completed.
74-
The `workflow` attribute holds the workflow instance involved, and the `action` attribute holds the action (transition) invoked.
66+
: Fired when a workflow event has completed.
67+
The `workflow` attribute holds the workflow instance involved, and the `action` attribute holds the action (transition) invoked.
7568

7669
Event handlers can be registered using ZCML with the `<subscriber />` directive.
7770

78-
As an example, lets add an event handler to the `Presenter` type.
79-
It tries to find users with matching names matching the presenter id, and send these users an email.
71+
As an example, let's add an event handler to the `Presenter` type.
72+
It tries to find users with matching names matching the presenter ID, and sends these users an email.
8073

81-
First, we require an additional import at the top of `presenter.py`:
74+
First, we require an additional import at the top of {file}`presenter.py`.
8275

8376
```python
8477
from plone import api
8578
```
8679

87-
Then, well add the following event subscriber after the schema definition:
80+
Then we'll add the following event subscriber after the schema definition.
8881

8982
```python
9083
def notifyUser(presenter, event):
91-
acl_users = api.portal.get_tool('acl_users')
92-
sender = api.portal.get_registry_record('plone.email_from_name')
84+
acl_users = api.portal.get_tool("acl_users")
85+
sender = api.portal.get_registry_record("plone.email_from_name")
9386

9487
if not sender:
9588
return
9689

97-
subject = 'Is this you?'
98-
message = 'A presenter called {0} was added here {1}'.format(
90+
subject = "Is this you?"
91+
message = "A presenter called {0} was added here {1}".format(
9992
presenter.title,
10093
presenter.absolute_url()
10194
)
10295

10396
matching_users = acl_users.searchUsers(fullname=presenter.title)
10497
for user_info in matching_users:
105-
email = user_info.get('email', None)
98+
email = user_info.get("email", None)
10699
if email is not None:
107100
api.portal.send_email(
108101
recipient=email,
@@ -112,11 +105,11 @@ def notifyUser(presenter, event):
112105
)
113106
```
114107

115-
And register it in ZCML:
108+
And register it in ZCML.
116109

117-
- First argument to `for` is an interface describing the object type.
118-
- Second argument is the event type.
119-
- The arguments to the function reflects these two, so the first argument is the `IPresenter` instance and the second is an `IObjectAddedEvent` instance.
110+
- The first argument to `for` is an interface describing the object type.
111+
- The second argument is the event type.
112+
- The arguments to the function reflects these two, so the first argument is the `IPresenter` instance, and the second is an `IObjectAddedEvent` instance.
120113

121114
```xml
122115
<subscriber
@@ -127,5 +120,3 @@ And register it in ZCML:
127120
```
128121

129122
There are many ways to improve this rather simplistic event handler, but it illustrates how events can be used.
130-
131-
[zope.event]: http://pypi.python.org/pypi/zope.event

0 commit comments

Comments
 (0)