-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
plugin_rendering.py
162 lines (149 loc) · 6.19 KB
/
plugin_rendering.py
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
# -*- coding: utf-8 -*-
from cms.models.placeholdermodel import Placeholder
from cms.plugin_processors import (plugin_meta_context_processor,
mark_safe_plugin_processor)
from cms.utils import get_language_from_request
from cms.utils.django_load import iterload_objects
from cms.utils.placeholder import (get_page_from_placeholder_if_exists,
get_placeholder_conf)
from django.conf import settings
from django.template import Template, Context
from django.template.defaultfilters import title
from django.template.loader import render_to_string
from django.utils.translation import ugettext_lazy as _
# these are always called before all other plugin context processors
DEFAULT_PLUGIN_CONTEXT_PROCESSORS = (
plugin_meta_context_processor,
)
# these are always called after all other plugin processors
DEFAULT_PLUGIN_PROCESSORS = (
mark_safe_plugin_processor,
)
class PluginContext(Context):
"""
This subclass of template.Context automatically populates itself using
the processors defined in CMS_PLUGIN_CONTEXT_PROCESSORS.
Additional processors can be specified as a list of callables
using the "processors" keyword argument.
"""
def __init__(self, dict, instance, placeholder, processors=None, current_app=None):
super(PluginContext, self).__init__(dict, current_app=current_app)
if not processors:
processors = []
for processor in DEFAULT_PLUGIN_CONTEXT_PROCESSORS:
self.update(processor(instance, placeholder))
for processor in iterload_objects(settings.CMS_PLUGIN_CONTEXT_PROCESSORS):
self.update(processor(instance, placeholder))
for processor in processors:
self.update(processor(instance, placeholder))
def render_plugin(context, instance, placeholder, template, processors=None,
current_app=None):
"""
Renders a single plugin and applies the post processors to it's rendered
content.
"""
if not processors:
processors = []
if isinstance(template, basestring):
content = render_to_string(template, context)
elif isinstance(template, Template):
content = template.render(context)
else:
content = ''
for processor in iterload_objects(settings.CMS_PLUGIN_PROCESSORS):
content = processor(instance, placeholder, content, context)
for processor in processors:
content = processor(instance, placeholder, content, context)
for processor in DEFAULT_PLUGIN_PROCESSORS:
content = processor(instance, placeholder, content, context)
return content
def render_plugins(plugins, context, placeholder, processors=None):
"""
Renders a collection of plugins with the given context, using the appropriate processors
for a given placeholder name, and returns a list containing a "rendered content" string
for each plugin.
This is the main plugin rendering utility function, use this function rather than
Plugin.render_plugin().
"""
c = []
total = len(plugins)
for index, plugin in enumerate(plugins):
plugin._render_meta.total = total
plugin._render_meta.index = index
context.push()
c.append(plugin.render_plugin(context, placeholder, processors=processors))
context.pop()
return c
def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder"):
"""
Renders plugins for a placeholder on the given page using shallow copies of the
given context, and returns a string containing the rendered output.
"""
from cms.plugins.utils import get_plugins
context = context_to_copy
context.push()
request = context['request']
plugins = [plugin for plugin in get_plugins(request, placeholder)]
page = get_page_from_placeholder_if_exists(placeholder)
if page:
template = page.template
else:
template = None
# Add extra context as defined in settings, but do not overwrite existing context variables,
# since settings are general and database/template are specific
# TODO this should actually happen as a plugin context processor, but these currently overwrite
# existing context -- maybe change this order?
slot = getattr(placeholder, 'slot', None)
extra_context = {}
if slot:
extra_context = get_placeholder_conf("extra_context", slot, template, {})
for key, value in extra_context.items():
if not key in context:
context[key] = value
c = []
# Prepend frontedit toolbar output if applicable
edit = False
toolbar = getattr(request, 'toolbar', None)
if (getattr(toolbar, 'edit_mode', False) and
(not page or page.has_change_permission(request))):
edit = True
if edit:
from cms.middleware.toolbar import toolbar_plugin_processor
processors = (toolbar_plugin_processor,)
else:
processors = None
c.extend(render_plugins(plugins, context, placeholder, processors))
content = "".join(c)
if edit:
content = render_placeholder_toolbar(placeholder, context, content, name_fallback)
context.pop()
return content
def render_placeholder_toolbar(placeholder, context, content, name_fallback=None):
from cms.plugin_pool import plugin_pool
request = context['request']
page = get_page_from_placeholder_if_exists(placeholder)
if not page:
page = getattr(request, 'current_page', None)
if page:
template = page.template
if name_fallback and not placeholder:
placeholder = Placeholder.objects.create(slot=name_fallback)
page.placeholders.add(placeholder)
else:
template = None
if placeholder:
slot = placeholder.slot
else:
slot = None
installed_plugins = plugin_pool.get_all_plugins(slot, page)
name = get_placeholder_conf("name", slot, template, title(slot))
name = _(name)
context.push()
context['installed_plugins'] = installed_plugins
context['language'] = get_language_from_request(request)
context['placeholder_label'] = name
context['placeholder'] = placeholder
context['page'] = page
toolbar = render_to_string("cms/toolbar/placeholder.html", context)
context.pop()
return "".join([toolbar, content])