1 .. _rendererhowto: |
1 .. _rendererhowto: |
2 |
2 |
3 |
3 |
4 How to create a new renderer? |
4 How to create a Renderer? |
5 ============================= |
5 ========================= |
|
6 |
|
7 |
|
8 **Renderer** are the layout of the utility data content. A renderer combine un context, a skin and |
|
9 a template to produce the front office html |
|
10 |
|
11 To create new renderer you can override an already exist renderer or create a new one from scratch. Steps below |
|
12 we will create a renderer for a `IContact` paragraph |
|
13 |
|
14 |
|
15 1. Override a Renderer |
|
16 ---------------------- |
|
17 |
|
18 The simplest is to create a new class that inherits from the existing **Renderer** and modify this template. |
|
19 After that all you have to define a new adapter name and a new label. |
|
20 |
|
21 |
|
22 .. code-block:: python |
|
23 :linenos: |
|
24 |
|
25 # New custom contact paragraph renderer |
|
26 |
|
27 @adapter_config(name='custom', context=(IContactParagraph, IPyAMSLayer), provides=IContentRenderer) |
|
28 @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer) |
|
29 class ContactParagraphCustomRenderer(ContactParagraphDefaultRenderer): |
|
30 """Context paragraph custom renderer""" |
|
31 |
|
32 label = _("Custom contact renderer") |
|
33 settings_interface = IContactParagraphDefaultRendererSettings |
|
34 |
|
35 |
|
36 In this example, we have defined an adapter named 'custom' with :py:class:`IContactParagraph`, |
|
37 :py:class:`IPyAMSLayer` as context and provides :py:class:`IContentRenderer` interface. |
|
38 |
|
39 Using ``@template_config()`` decorator, the renderer will be displayed in html container according to the template |
|
40 |
|
41 The new renderer inherit of :py:class:`ContactParagraphDefaultRenderer`, have a new **label** (line 8) |
|
42 and is associated an **settings_interface** (line 9) |
|
43 |
|
44 .. tip:: |
|
45 |
|
46 You can override the template of a renderer easily with the function :py:func:`pyams_template.template.override_template` |
|
47 It's takes the context and the new template path as params. |
|
48 |
|
49 |
|
50 2. Create a new Renderer from scratch |
|
51 ------------------------------------- |
|
52 |
|
53 We can define a new settings interface for the renderer, to do that we start by creating an interface |
|
54 |
|
55 |
|
56 a) Create setting interface for the renderer |
|
57 """""""""""""""""""""""""""""""""""""""""""" |
|
58 |
|
59 .. code-block:: python |
|
60 |
|
61 class IPhotoRendererSettings(Interface): |
|
62 """Custom renderer settings interface""" |
|
63 |
|
64 |
|
65 display_photo = Bool(title=_("Show photo?"), |
|
66 description=_("Display contact photo"), |
|
67 required=True, |
|
68 default=True) |
|
69 |
|
70 can_display_photo = Attribute("Check if photo can be displayed") |
|
71 |
|
72 |
|
73 We have created an interface with two attributes *display_photo* and *can_display_photo* |
|
74 Then we create an implemantation of the interface |
|
75 |
|
76 .. code-block:: python |
|
77 |
|
78 @implementer(IPhotoRendererSettings) |
|
79 class PhotoRendererSettings(Persistent, Location): |
|
80 """Custom renderer settings""" |
|
81 |
|
82 display_photo = FieldProperty(IPhotoRendererSettings['display_photo']) |
|
83 |
|
84 @property |
|
85 def can_display_photo(self): |
|
86 contact = IContactParagraph(self.__parent__) |
|
87 if not contact.photo: |
|
88 return False |
|
89 return self.display_photo |
|
90 |
|
91 |
|
92 |
|
93 b) Create an adapter for the render setting interface |
|
94 """"""""""""""""""""""""""""""""""""""""""""""""""""" |
|
95 |
|
96 With :py:func:`@adapter_config()` we declare a new adapter that applies to a context and provide the interface of |
|
97 renderer settings |
|
98 |
|
99 .. code-block:: python |
|
100 |
|
101 PHOTO_RENDERER_SETTINGS_KEY = 'pyams_content.contact.renderer:photo' |
|
102 |
|
103 @adapter_config(context=IContactParagraph, provides=IPhotoRendererSettings) |
|
104 def custom_renderer_settings_factory(context): |
|
105 """Contact paragraph default renderer settings factory""" |
|
106 return get_annotation_adapter(context, PHOTO_RENDERER_SETTINGS_KEY, |
|
107 CustomRendererSettings) |
|
108 |
|
109 |
|
110 In this example the settings interface adapter is defined with `IContactParagraph` as context |
|
111 and provide `IPhotoRendererSettings`. |
|
112 |
|
113 |
|
114 |
|
115 c) Create an adapter for the render interface |
|
116 """"""""""""""""""""""""""""""""""""""""""""" |
|
117 |
|
118 .. code-block:: python |
|
119 |
|
120 @adapter_config(context=(IContactParagraph, IPyAMSLayer), provides=IContentRenderer) |
|
121 @template_config(template='templates/contact-custom.pt', layer=IPyAMSLayer) |
|
122 class PhotoRenderer(BaseContentRenderer): |
|
123 """Context paragraph custom renderer""" |
|
124 |
|
125 label = _("Custom contact renderer") |
|
126 settings_interface = IPhotoRendererSettings |
|
127 |
|
128 |
|
129 Add settings interface to the renderer `settings_interface = IPhotoRendererSettings` |
|
130 |
|
131 .. tip:: |
|
132 When a setting_interface is associated to a renderer, you can access to `settings` attributes through the template |
|
133 |