-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
custom_plugins.txt
225 lines (156 loc) · 7.56 KB
/
custom_plugins.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
You have three options to extend Django CMS: Custom plugins, plugin context
processors, and plugin processors.
Custom Plugins
==============
Suppose you have the following gallery model::
class Gallery(models.Model):
name = models.CharField(max_length=30)
class Picture(models.Model):
gallery = models.ForeignKey(Gallery)
image = models.ImageField(upload_to="uploads/images/")
description = models.CharField(max_length=60)
And that you want to display this gallery between two text blocks.
You can do this with a CMS plugin. To create a CMS plugin you need two
components: a CMSPlugin model and a cms_plugins.py file.
Plugin Model
------------
First create a model that links to the gallery via a ForeignKey field::
from cms.models import CMSPlugin
class GalleryPlugin(CMSPlugin):
gallery = models.ForeignKey(Gallery)
Be sure that your model inherits the CMSPlugin class.
The plugin model can have any fields it wants. They are the fields that
get displayed if you edit the plugin.
cms_plugins.py
--------------
After that create in the application folder (the same one where models.py is) a cms_plugins.py file.
In there write the following::
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from models import GalleryPlugin
from django.utils.translation import ugettext as _
class CMSGalleryPlugin(CMSPluginBase):
model = GalleryPlugin
name = _("Gallery")
render_template = "gallery/gallery.html"
def render(self, context, instance, placeholder):
context.update({'gallery':instance.gallery,
'object':instance,
'placeholder':placeholder})
return context
plugin_pool.register_plugin(CMSGalleryPlugin)
CMSPluginBase itself inherits from ModelAdmin so you can use all the things (inlines for example) you would
use in a regular admin class.
For a list of all the options you have on CMSPluginBase have a look at the plugin reference
Template
--------
Now create a gallery.html template in ``templates/gallery/`` and write the following in there.
::
{% for image in gallery.picture_set.all %}
<img src="{{ image.image.url }}" alt="{{ image.description }}" />
{% endfor %}
Now go into the admin create a gallery and afterwards go into a page and add a gallery plugin and some
pictures should appear in your page.
Limiting Plugins per Placeholder
--------------------------------
You can limit in which placeholder certain plugins can appear. Add a ``CMS_PLACEHOLDER_CONF`` to your ``settings.py``.
Example::
CMS_PLACEHOLDER_CONF = {
'content': {
"plugins": ('ContactFormPlugin','FilePlugin','FlashPlugin','LinkPlugin','PicturePlugin','TextPlugin'),
"extra_context": {"width":940},
"name": gettext("content")
},
'right-column': {
"plugins": ('ContactFormPlugin','TextPlugin', 'SimpleGalleryPublicationPlugin'),
"extra_context": {"width":280},
"name": gettext("right column")
"limits": {
"global": 2,
"TeaserPlugin": 1,
"LinkPlugin": 1,
},
},
"**content**" and "**right-column**" are the names of two placeholders. The plugins list are filled with
Plugin class names you find in the ``cms_plugins.py``. You can add extra context to each placeholder so
plugin-templates can react to them. In this example we give them some parameters that are used in a
CSS Grid Framework.
You can change the displayed name in the admin with the **name** parameter. In combination with gettext
you can translate this names according to the language of the user. Additionally you can limit the number
of plugins (either total or by type) for each placeholder with the **limits** parameter (see
``Configuration`` for details).
Advanced
--------
CMSGalleryPlugin can be even further customized:
Because CMSPluginBase extends ModelAdmin from django.contrib.admin you can use all the things you are used
to with normal admin classes. You can defined inlines, the form, the form template etc.
Note: If you want to overwrite the form be sure to extend from ``admin/cms/page/plugin_change_form.html``
to have an unified look across the plugins and to have the preview functionality automatically installed.
Plugin Context Processors
-------------------------
Plugin context processors are callables that modify all plugin's context before rendering. They are enabled
using the ``CMS_PLUGIN_CONTEXT_PROCESSORS`` setting.
A plugin context processor takes 2 arguments:
**instance**:
The instance of the plugin model
**placeholder**:
The instance of the placeholder this plugin appears in.
The return value should be a dictionary containing any variables to be added to the context.
Example::
# settings.py:
CMS_PLUGIN_CONTEXT_PROCESSORS = (
'yourapp.cms_plugin_context_processors.add_verbose_name',
)
# yourapp.cms_plugin_context_processors.py:
def add_verbose_name(instance, placeholder):
'''
This plugin context processor adds the plugin model's verbose_name to context.
'''
return {'verbose_name': instance._meta.verbose_name}
Plugin Processors
-----------------
Plugin processors are callables that modify all plugin's output after rendering. They are enabled using
the ``CMS_PLUGIN_PROCESSORS`` setting.
A plugin processor takes 4 arguments:
**instance**:
The instance of the plugin model
**placeholder**:
The instance of the placeholder this plugin appears in.
**rendered_content**:
A string containing the rendered content of the plugin.
**original_context**:
The original context for the template used to render the plugin.
Note that plugin processors are also applied to plugins embedded in Text. Depending on what your processor
does, this might break the output. For example, if your processor wraps the output in a DIV tag, you might
end up having DIVs inside of P tags, which is invalid. You can prevent such cases by returning
`rendered_content` unchanged if `instance._render_meta.text_enabled` is True, which is the case when
rendering an embedded plugin.
Example:
Suppose you want to put wrap each plugin in the main placeholder in a colored box, but it would be too
complicated to edit each individual plugin's template:
In your settings.py::
CMS_PLUGIN_PROCESSORS = (
'yourapp.cms_plugin_processors.wrap_in_colored_box',
)
In your yourapp.cms_plugin_processors.py::
def wrap_in_colored_box(instance, placeholder, rendered_content, original_context):
'''
This plugin processor wraps each plugin's output in a colored box if it is in the "main" placeholder.
'''
if placeholder.slot != 'main' \ # Plugins not in the main placeholder should remain unchanged
or instance._render_meta.text_enabled: # Plugins embedded in Text should remain unchanged in order not to break output
return rendered_content
else:
from django.template import Context, Template
# For simplicity's sake, construct the template from a string:
t = Template('<div style="border: 10px {{ border_color }} solid; background: {{ background_color }};">{{ content|safe }}</div>')
# Prepare that template's context:
c = Context({
'content': rendered_content,
# Some plugin models might allow you to customize the colors,
# for others, use default colors:
'background_color': instance.background_color if hasattr(instance, 'background_color') else 'lightyellow',
'border_color': instance.border_color if hasattr(instance, 'border_color') else 'lightblue',
})
# Finally, render the content through that template, and return the output
return t.render(c)