|
1 | 1 | --- |
2 | 2 | myst: |
3 | 3 | html_meta: |
4 | | - "description": "" |
5 | | - "property=og:description": "" |
6 | | - "property=og:title": "" |
7 | | - "keywords": "" |
| 4 | + "description": "How to add a custom content class implementation in Plone" |
| 5 | + "property=og:description": "How to add a custom content class implementation in Plone" |
| 6 | + "property=og:title": "How to add a custom content class implementation in Plone" |
| 7 | + "keywords": "Plone, custom, content, class" |
8 | 8 | --- |
9 | 9 |
|
10 | 10 | # Custom content classes |
11 | 11 |
|
12 | | -**Adding a custom implementation** |
| 12 | +This chapter describes how to add a custom content class implementation. |
13 | 13 |
|
14 | | -When we learned about configuring the Dexterity FTI, |
15 | | -we saw the `klass` attribute and how it could be used to refer to either |
16 | | -the `Container` or `Item` content classes. |
17 | | -These classes are defined in the [plone.dexterity.content] module, |
18 | | -and represent container (folder) and item (non-folder) types, respectively. |
| 14 | +When we learned about configuring the Dexterity FTI, we saw the `klass` attribute and how it could be used to refer to either the `Container` or `Item` content classes. |
| 15 | +These classes are defined in the [`plone.dexterity.content`](https://github.com/plone/plone.dexterity/blob/master/plone/dexterity/content.py) module, and represent container (folder) and item (non-folder) types, respectively. |
19 | 16 |
|
20 | 17 | For most applications, these two classes will suffice. |
21 | | -We will normally use behaviors, adapters, event handlers and schema |
22 | | -interfaces to build additional functionality for our types. |
23 | | -In some cases, however, it is useful or necessary to override the class, |
24 | | -typically to override some method or property provided by the base class |
25 | | -that cannot be implemented with an adapter override. |
26 | | -A custom class may also be able to provide marginally better performance by |
27 | | -side-stepping some of the schema-dependent dynamic behavior found in the |
28 | | -base classes. |
| 18 | +We will normally use behaviors, adapters, event handlers, and schema interfaces to build additional functionality for our types. |
| 19 | +In some cases, however, it is useful or necessary to override the class, typically to override some method or property provided by the base class that cannot be implemented with an adapter override. |
| 20 | +A custom class may also be able to provide marginally better performance by side-stepping some of the schema-dependent dynamic behavior found in the base classes. |
29 | 21 | In real life, you are very unlikely to notice, though. |
30 | 22 |
|
31 | | -Creating a custom class is simple: simply derive from one of the |
32 | | -standard ones, e.g.: |
| 23 | +To create a custom class, derive from one of the standard ones, as shown below |
33 | 24 |
|
34 | | -``` |
| 25 | +```python |
35 | 26 | from plone.dexterity.content import Item |
36 | 27 |
|
37 | 28 | class MyItem(Item): |
38 | 29 | """A custom content class""" |
39 | | - ... |
40 | 30 | ``` |
41 | 31 |
|
42 | | -For a container type, we’d do: |
| 32 | +For a container type, we'd do the following |
43 | 33 |
|
44 | | -``` |
| 34 | +```python |
45 | 35 | from plone.dexterity.content import Container |
46 | 36 |
|
47 | 37 | class MyContainer(Container): |
48 | 38 | """A custom content class""" |
49 | | - ... |
50 | 39 | ``` |
51 | 40 |
|
52 | 41 | You can now add any required attributes or methods to this class. |
53 | 42 |
|
54 | | -To make use of this class, set the `klass` attribute in the FTI to its |
55 | | -dotted name, e.g. |
| 43 | +To make use of this class, set the `klass` attribute in the FTI to its dotted name, as shown in the following example. |
56 | 44 |
|
57 | 45 | ```xml |
58 | 46 | <property name="klass">my.package.myitem.MyItem</property> |
59 | 47 | ``` |
60 | 48 |
|
61 | | -This will cause the standard Dexterity factory to instantiate this class |
62 | | -when the user submits the add form. |
| 49 | +This will cause the standard Dexterity factory to instantiate this class when the user submits the add form. |
| 50 | + |
| 51 | +```{note} |
| 52 | +As an alternative to setting `klass` in the FTI, you may provide your own `IFactory` utility for this type in lieu of Dexterity's default factory (see [plone.dexterity.factory](https://github.com/plone/plone.dexterity/blob/master/plone/dexterity/factory.py)). |
| 53 | +However, you need to be careful that this factory performs all necessary initialization, so it is normally better to use the standard factory. |
| 54 | +``` |
63 | 55 |
|
64 | | -:::{note} |
65 | | -As an alternative to setting `klass` in the FTI, |
66 | | -you may provide your own `IFactory` utility for this type in lieu of |
67 | | -Dexterity’s default factory (see [plone.dexterity.factory]). |
68 | | -However, you need to be careful that this factory performs all necessary |
69 | | -initialisation, so it is normally better to use the standard factory. |
70 | | -::: |
71 | 56 |
|
72 | 57 | ## Custom class caveats |
73 | 58 |
|
74 | 59 | There are a few important caveats when working with custom content classes: |
75 | 60 |
|
76 | | -- Make sure you use the correct base class: either |
77 | | - `plone.dexterity.content.Item` or |
| 61 | +- Make sure you use the correct base class: either `plone.dexterity.content.Item` or |
78 | 62 | `plone.dexterity.content.Container`. |
79 | | -- If you mix in other base classes, |
80 | | - it is safer to put the `Item` or `Container` class first. |
81 | | - If another class comes first, it may override the `__name__`, |
82 | | - `__providedBy__`, `__allow_access_to_unprotected_subobjects__` and/or |
83 | | - `isPrincipiaFolderish` properties, and possibly the `__getattr__()` |
84 | | - and `__getitem__()` methods, |
85 | | - causing problems with the dynamic schemata and/or folder item security. |
86 | | - In all cases, you may need to explicitly set these attributes to the ones |
87 | | - from the correct base class. |
88 | | -- If you define a custom constructor, make sure it can be called with |
89 | | - no arguments, and with an optional `id` argument giving the name. |
90 | | - |
91 | | -[plone.dexterity.content]: http://pypi.python.org/pypi/plone.dexterity.content |
92 | | -[plone.dexterity.factory]: http://pypi.python.org/pypi/plone.dexterity.factory |
| 63 | +- If you mix in other base classes, it is safer to put the `Item` or `Container` class first. |
| 64 | + If another class comes first, it may override the `__name__`, `__providedBy__`, `__allow_access_to_unprotected_subobjects__`, or `isPrincipiaFolderish` properties, and possibly the `__getattr__()` and `__getitem__()` methods, causing problems with the dynamic schemata or folder item security. |
| 65 | + In all cases, you may need to explicitly set these attributes to the ones from the correct base class. |
| 66 | +- If you define a custom constructor, make sure it can be called with no arguments, and with an optional `id` argument giving the name. |
0 commit comments