0
# Plugin System
1
2
Django CMS features an extensible plugin architecture that allows modular content components to be inserted into placeholders, with support for custom plugin development, nested plugins, and comprehensive plugin management.
3
4
## Capabilities
5
6
### Plugin Management
7
8
Add, configure, and manage plugins within placeholders with full control over positioning and hierarchy.
9
10
```python { .api }
11
def add_plugin(
12
placeholder,
13
plugin_type,
14
language,
15
position="last-child",
16
target=None,
17
**data
18
):
19
"""
20
Add a plugin to a placeholder.
21
22
Args:
23
placeholder (Placeholder): Target placeholder
24
plugin_type (str): Plugin type identifier
25
language (str): Language code
26
position (str): Position relative to target ("first-child", "last-child", "left", "right")
27
target (CMSPlugin, optional): Reference plugin for positioning
28
**data: Plugin-specific configuration data
29
30
Returns:
31
CMSPlugin: Created plugin instance
32
"""
33
```
34
35
### Plugin Base Classes
36
37
Foundation classes for developing custom plugins with admin integration, rendering, and configuration.
38
39
```python { .api }
40
class CMSPluginBase:
41
"""
42
Base class for all CMS plugins.
43
44
Attributes:
45
model: Plugin model class
46
name: Human-readable plugin name
47
render_template: Template for frontend rendering
48
admin_preview: Show preview in admin
49
allow_children: Allow child plugins
50
child_classes: Allowed child plugin types
51
parent_classes: Allowed parent plugin types
52
require_parent: Require parent plugin
53
text_enabled: Enable text plugin features
54
cache: Enable plugin caching
55
"""
56
57
def render(self, context, instance, placeholder):
58
"""Render plugin content."""
59
60
def get_render_template(self, context, instance, placeholder):
61
"""Get template for rendering."""
62
63
def get_form(self, request, obj=None, **kwargs):
64
"""Get admin form for plugin."""
65
66
def save_model(self, request, obj, form, change):
67
"""Save plugin instance."""
68
69
class CMSPluginBaseMetaclass:
70
"""Metaclass for automatic plugin registration."""
71
72
class PluginMenuItem:
73
"""Configuration for plugin menu items."""
74
```
75
76
### Plugin Models
77
78
Core models for plugin data storage and hierarchy management.
79
80
```python { .api }
81
class CMSPlugin:
82
"""
83
Base model for all plugin instances.
84
85
Attributes:
86
placeholder: Associated placeholder
87
parent: Parent plugin for nesting
88
position: Position within placeholder
89
language: Language code
90
plugin_type: Plugin type identifier
91
creation_date: Creation timestamp
92
changed_date: Last modification timestamp
93
numchild: Number of child plugins
94
depth: Nesting depth level
95
path: Tree path for hierarchy
96
"""
97
98
def get_plugin_class(self):
99
"""Get plugin class instance."""
100
101
def get_plugin_instance(self, admin=None):
102
"""Get downcasted plugin instance."""
103
104
def get_bound_plugin(self):
105
"""Get bound plugin with class."""
106
107
def copy_relations(self, old_instance):
108
"""Copy plugin relationships."""
109
110
class AliasPlugin:
111
"""Plugin for referencing other plugins."""
112
113
class PlaceholderPlugin:
114
"""Plugin containing nested placeholder."""
115
```
116
117
### Plugin Pool Management
118
119
Global registry for plugin types and plugin discovery.
120
121
```python { .api }
122
class PluginPool:
123
"""Global plugin registry and management."""
124
125
def register_plugin(self, plugin_class):
126
"""Register a plugin class."""
127
128
def unregister_plugin(self, plugin_class):
129
"""Unregister a plugin class."""
130
131
def get_all_plugins(self, placeholder=None, page=None, setting_key="plugins"):
132
"""Get available plugins for context."""
133
134
def get_text_enabled_plugins(self, placeholder, page):
135
"""Get text-enabled plugins."""
136
137
# Global plugin pool instance
138
plugin_pool = PluginPool()
139
```
140
141
## Usage Examples
142
143
### Adding Plugins to Pages
144
145
```python
146
from cms.api import create_page, add_plugin
147
from cms.models import Placeholder
148
149
# Create a page
150
page = create_page(
151
title="Sample Page",
152
template="page.html",
153
language="en"
154
)
155
156
# Get a placeholder
157
placeholder = page.get_placeholders("en").get(slot="content")
158
159
# Add a text plugin
160
text_plugin = add_plugin(
161
placeholder=placeholder,
162
plugin_type="TextPlugin",
163
language="en",
164
body="<h1>Welcome!</h1><p>This is sample content.</p>"
165
)
166
167
# Add an image plugin after the text
168
image_plugin = add_plugin(
169
placeholder=placeholder,
170
plugin_type="PicturePlugin",
171
language="en",
172
position="right",
173
target=text_plugin,
174
picture="/path/to/image.jpg",
175
alt_text="Sample image"
176
)
177
178
# Add a nested plugin structure
179
container_plugin = add_plugin(
180
placeholder=placeholder,
181
plugin_type="MultiColumnPlugin",
182
language="en"
183
)
184
185
column_plugin = add_plugin(
186
placeholder=placeholder,
187
plugin_type="ColumnPlugin",
188
language="en",
189
parent=container_plugin,
190
width="50%"
191
)
192
```
193
194
### Custom Plugin Development
195
196
```python
197
from cms.plugin_base import CMSPluginBase
198
from cms.plugin_pool import plugin_pool
199
from django import forms
200
from django.db import models
201
202
# Plugin model
203
class CallToActionPlugin(models.Model):
204
title = models.CharField(max_length=100)
205
description = models.TextField()
206
button_text = models.CharField(max_length=50)
207
button_url = models.URLField()
208
209
def __str__(self):
210
return self.title
211
212
# Plugin class
213
@plugin_pool.register_plugin
214
class CallToActionPluginPublisher(CMSPluginBase):
215
model = CallToActionPlugin
216
name = "Call to Action"
217
render_template = "plugins/call_to_action.html"
218
cache = True
219
220
fieldsets = (
221
('Content', {
222
'fields': ('title', 'description')
223
}),
224
('Button', {
225
'fields': ('button_text', 'button_url')
226
}),
227
)
228
229
def render(self, context, instance, placeholder):
230
context['instance'] = instance
231
return context
232
```
233
234
### Working with Plugin Hierarchy
235
236
```python
237
from cms.models import CMSPlugin
238
from cms.utils.plugins import copy_plugins_to_placeholder
239
240
# Get all plugins in a placeholder
241
plugins = CMSPlugin.objects.filter(
242
placeholder=placeholder,
243
language="en"
244
).order_by('path')
245
246
# Get root level plugins only
247
root_plugins = plugins.filter(parent=None)
248
249
# Get child plugins of a specific plugin
250
child_plugins = plugins.filter(parent=parent_plugin)
251
252
# Copy plugins to another placeholder
253
copy_plugins_to_placeholder(
254
plugins=plugins,
255
placeholder=target_placeholder,
256
language="en"
257
)
258
259
# Move plugin to different position
260
plugin.move(target_plugin, position="right")
261
plugin.save()
262
```
263
264
### Plugin Utilities
265
266
```python
267
from cms.utils.plugins import (
268
get_bound_plugins,
269
has_reached_plugin_limit,
270
get_plugin_class
271
)
272
273
# Get plugin instances with their classes
274
bound_plugins = get_bound_plugins(plugins)
275
276
# Check plugin limits
277
can_add = not has_reached_plugin_limit(
278
placeholder=placeholder,
279
plugin_type="TextPlugin",
280
language="en",
281
template="page.html"
282
)
283
284
# Get plugin class by type
285
plugin_class = get_plugin_class("TextPlugin")
286
```
287
288
## Types
289
290
```python { .api }
291
class Placeholder:
292
"""
293
Container for plugins within templates.
294
295
Attributes:
296
slot: Placeholder name/identifier
297
default_width: Default width for plugins
298
locked: Whether placeholder is locked
299
"""
300
301
def get_plugins(self, language=None):
302
"""Get plugins for language."""
303
304
def get_label(self):
305
"""Get placeholder display label."""
306
307
def is_editable(self, request):
308
"""Check if placeholder is editable."""
309
310
class PlaceholderReference:
311
"""Reference to placeholder for generic relationships."""
312
```