class StaticPlaceholderNode(Tag): name = 'static_placeholder' options = PlaceholderOptions(Argument('code', required=True), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endstatic_placeholder', 'nodelist'), ]) def render_tag(self, context, code, extra_bits, nodelist=None): # TODO: language override (the reason this is not implemented, is that language selection is buried way # down somewhere in some method called in render_plugins. There it gets extracted from the request # and a language in request.GET always overrides everything.) if not code: # an empty string was passed in or the variable is not available in the context if nodelist: return nodelist.render(context) return '' request = context.get('request', False) if not request: if nodelist: return nodelist.render(context) return '' if isinstance(code, StaticPlaceholder): static_placeholder = code else: if 'site' in extra_bits: site = Site.objects.get_current() static_placeholder, __ = StaticPlaceholder.objects.get_or_create( code=code, site_id=site.pk, defaults={ 'name': code, 'creation_method': StaticPlaceholder.CREATION_BY_TEMPLATE }) else: static_placeholder, __ = StaticPlaceholder.objects.get_or_create( code=code, site_id__isnull=True, defaults={ 'name': code, 'creation_method': StaticPlaceholder.CREATION_BY_TEMPLATE }) if not hasattr(request, 'static_placeholders'): request.static_placeholders = [] request.static_placeholders.append(static_placeholder) if hasattr(request, 'toolbar') and request.toolbar.edit_mode: placeholder = static_placeholder.draft else: placeholder = static_placeholder.public placeholder.is_static = True content = render_placeholder(placeholder, context, name_fallback=code, default=nodelist) return content
class Placeholder(Tag): """ This template node is used to output page content and is also used in the admin to dynamically generate input fields. eg: {% placeholder "placeholder_name" %} {% placeholder "sidebar" inherit %} {% placeholder "footer" inherit or %} <a href="/about/">About us</a> {% endplaceholder %} Keyword arguments: name -- the name of the placeholder inherit -- optional argument which if given will result in inheriting the content of the placeholder with the same name on parent pages or -- optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = 'placeholder' options = PlaceholderOptions( Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ], ) def render_tag(self, context, name, extra_bits, nodelist=None): validate_placeholder_name(name) content_renderer = context.get('cms_content_renderer') if not content_renderer: return '' inherit = 'inherit' in extra_bits content = content_renderer.render_page_placeholder( slot=name, context=context, inherit=inherit, nodelist=nodelist, ) return content def get_name(self): return self.kwargs['name'].var.value.strip('"').strip("'") def get_inherit_status(self): flags = self.kwargs['extra_bits'] if not isinstance(flags, ListValue): return False for extra in self.kwargs['extra_bits']: if extra.var.value.strip() == 'inherit': return True return False
class Placeholder(Tag): """ This template node is used to output page content and is also used in the admin to dynamically generate input fields. eg: {% placeholder "placeholder_name" %} {% placeholder "sidebar" inherit %} {% placeholder "footer" inherit or %} <a href="/about/">About us</a> {% endplaceholder %} Keyword arguments: name -- the name of the placeholder inherit -- optional argument which if given will result in inheriting the content of the placeholder with the same name on parent pages or -- optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = 'placeholder' options = PlaceholderOptions(Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ]) def render_tag(self, context, name, extra_bits, nodelist=None): validate_placeholder_name(name) inherit = False for bit in extra_bits: if bit == 'inherit': inherit = True if not 'request' in context: return '' request = context['request'] page = request.current_page if not page or page == 'dummy': if nodelist: return nodelist.render(context) return '' content = '' try: content = get_placeholder_content(context, request, page, name, inherit, nodelist) except PlaceholderNotFound: if nodelist: return nodelist.render(context) if not content: if nodelist: return nodelist.render(context) return '' return content def get_name(self): return self.kwargs['name'].var.value.strip('"').strip("'")
def handle_as_arg(self, value, kwargs): if self.name in kwargs: if self.max_values and len(kwargs[self.name]) == self.max_values: return False kwargs[self.name].append(value) else: kwargs[self.name] = MultiValueArgument.sequence_class(value) return True
class ArticlePlaceholder(Tag): """ This template node is used to output article content and is also used in the admin to dynamically generate input fields. eg: {% article_placeholder "placeholder_name" %} {% article_placeholder "footer" or %} <a href="/about/">About us</a> {% endarticle_placeholder %} Keyword arguments: name -- the name of the placeholder or -- optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = 'article_placeholder' options = PlaceholderOptions( Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endarticle_placeholder', 'nodelist'), ], ) def render_tag(self, context, name, extra_bits, nodelist=None): request = context.get('request') if not request: return '' validate_placeholder_name(name) toolbar = get_toolbar_from_request(request) renderer = toolbar.get_content_renderer() inherit = False try: content = renderer.render_page_placeholder( slot=name, context=context, inherit=inherit, page=request.current_article, nodelist=nodelist, ) except PlaceholderNotFound: content = '' if not content and nodelist: return nodelist.render(context) return content def get_declaration(self): slot = self.kwargs['name'].var.value.strip('"').strip("'") return DeclaredPlaceholder(slot=slot, inherit=False)
class StaticPlaceholderNode(Tag): name = 'static_placeholder' options = PlaceholderOptions(Argument('code', required=True), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endstatic_placeholder', 'nodelist'), ]) def render_tag(self, context, code, extra_bits, nodelist=None): request = context.get('request') if not code or not request: # an empty string was passed in or the variable is not available in the context if nodelist: return nodelist.render(context) return '' toolbar = get_toolbar_from_request(request) renderer = toolbar.get_content_renderer() if isinstance(code, StaticPlaceholder): static_placeholder = code else: kwargs = { 'code': code, 'defaults': { 'creation_method': StaticPlaceholder.CREATION_BY_TEMPLATE } } if 'site' in extra_bits: kwargs['site'] = get_current_site() else: kwargs['site_id__isnull'] = True static_placeholder = StaticPlaceholder.objects.get_or_create( **kwargs)[0] content = renderer.render_static_placeholder( static_placeholder, context=context, nodelist=nodelist, ) return content def get_declaration(self, context): flags = self.kwargs['extra_bits'] slot = self.kwargs['code'].resolve(context) if isinstance(flags, ListValue): site_bound = any(extra.var.value.strip() == 'site' for extra in flags) return DeclaredStaticPlaceholder(slot=slot, site_bound=site_bound) return DeclaredStaticPlaceholder(slot=slot, site_bound=False)
class FieldsetTag(Tag): """ FieldsetTag renders fieldset with specified fields in it. **Usage:** :: {% fieldset 'field1' 'field2' [title 'MyFieldset'] %} {% fieldset unused_fields %} """ name = 'fieldset' options = Options( MultiValueArgument('fields'), 'title', Argument('title', required=False), ) template = 'zenforms/fieldset.html' def udpate_context(self, fields, form, tag_context, unused_fields): if type(fields) is list and fields[0] == unused_fields: # ``unused_fields`` is the argument iterable = tuple(unused_fields) else: iterable = fields for field in iterable: try: if type(field) in [SafeUnicode, str]: tag_context['fields'].append(form[field]) unused_fields.remove(field) elif type(field) is MultiField: tag_context['fields'].append(field) for fname in field.field_names: unused_fields.remove(fname) elif type(field) is ReadonlyField: tag_context['fields'].append(field) except KeyError: raise TemplateError('form does not contain field %s' % field) def get_context(self, context, title, fields): tag_context = {'fields': [], 'title': title} try: form = context['form'] unused_fields = context['unused_fields'] except KeyError: raise TemplateError( 'fieldset tag must be used in {% zenform %}{% endzenform %} context' ) self.udpate_context(fields, form, tag_context, unused_fields) context.update(tag_context) return context def render_tag(self, context, title, fields): context = self.get_context(context, title, fields) template = loader.get_template(self.template) output = template.render(context) return output
class GetSlot(AsTag): name = 'get_slot' options = Options( MultiValueArgument('keys', required=False, resolve=True), 'as', Argument('varname', required=False, resolve=False, default="slot")) def get_value(self, context, keys): key = get_key(context, keys) slot, created = models.Slot.objects.get_or_create(key=key) return slot
class Rule(AsTag): options = Options( Argument('rule_name'), MultiValueArgument('args', required=False), MultiKeywordArgument('kwargs', required=False), 'as', Argument('varname', resolve=False, required=False), ) def get_value(self, context, rule_name, args, kwargs): return rules_light.run(context['request'].user, rule_name, *args, **kwargs)
class GetPlaceholderPlugins(Tag): """ A template tag that gets plugins from a page's placeholder and sets them as a context variable: {% get_placeholder_plugins "logo" page_lookup as varname %} {% get_placeholder_plugins "logo" page_lookup as varname or %} <div>No content</div> {% endget_placeholder_plugins %} The page_lookup parameter can be omitted and will default to the current page {% get_placeholder_plugins "logo" as varname %} {% get_placeholder_plugins "logo" as varname or %} <div>No content</div> {% endget_placeholder_plugins %} This tag can typically be used in association with the block_plugin tag, to render the retrieved plugins: {% get_placeholder_plugins "logo" page_lookup as plugins %} {% blockplugin plugins.0 %} <img src="{% thumbnail instance.picture 300x150 %}"/> {% endblockplugin %} Keyword arguments: name: the name of the placeholder page_lookup: lookup argument for Page. See `_get_page_by_untyped_arg()` for detailed information on the allowed types and their interpretation for the `page_lookup` argument. varname: context variable name. Output will be added to template context as this variable instead of being returned. or: optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = "get_placeholder_plugins" options = PlaceholderOptions( Argument("name", resolve=False), Argument("page_lookup", required=False, default=None), "as", Argument("varname", resolve=False), MultiValueArgument("extra_bits", required=False, resolve=False), blocks=[("endget_placeholder_plugins", "nodelist")], ) # pylint: disable=arguments-differ,too-many-arguments, unused-argument def render_tag( self, context, name, page_lookup, varname, extra_bits, nodelist=None ): return get_plugins_render_tag( context, name, varname, nodelist, page_lookup, edit=False )
class GetGrid(AsTag): name = 'get_grid' options = Options( MultiValueArgument('keys', required=False, resolve=False), 'as', Argument('varname', required=False, resolve=False, default="grid") ) def get_value(self, context, keys): key = get_key(context, keys) grid, created = models.Grid.objects.get_or_create(key=key) return grid
class PlaceholderAttr(Tag): name = 'placeholder_attr' options = PlaceholderOptions(Argument('name', resolve=False), Argument('plugin_class_name', resolve=False), Argument('plugin_attr', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ]) def render_tag(self, context, name, plugin_class_name, plugin_attr, extra_bits, nodelist=None): validate_placeholder_name(name) width = None for bit in extra_bits: if bit == 'inherit': pass elif bit.isdigit(): width = int(bit) import warnings warnings.warn( "The width parameter for the placeholder " + "tag is deprecated.", DeprecationWarning) if not 'request' in context: return '' request = context['request'] if width: context.update({'width': width}) page = request.current_page if not page or page == 'dummy': if nodelist: return nodelist.render(context) return '' placeholder = _get_placeholder(page, page, context, name) res = get_placholder_attr(placeholder, name, plugin_class_name, plugin_attr) return res
class ReadonlyTag(Tag): name = 'readonly' template = 'zenforms/fields/readonly.html' options = Options( Argument('instance'), MultiValueArgument('fields'), 'label', Argument('label', required=False, default=None), 'as', Argument('varname', resolve=False, required=False, default=None), ) def get_context(self, instance, field_names, label): opts = instance._meta context = {} fields = [] for fname in field_names: try: f = opts.get_field_by_name(fname)[0] except FieldDoesNotExist: raise TemplateError('Field %s not exists in a model' % fname) else: fields.append({ 'value': f.value_from_object(instance), 'meta': f }) context['fields'] = fields if label: context['label'] = label else: context['label'] = fields[0]['meta'].verbose_name context['help_text'] = fields[0]['meta'].help_text return context def render_tag(self, context, instance, fields, label, varname): ctx = self.get_context(instance, fields, label) if varname: context[varname] = ReadonlyField(**ctx) return u'' else: context.push() context.update({'readonly': ctx}) template = loader.get_template(self.template) output = template.render(context) context.pop() return output
class RenderSlot(InclusionTag): name = 'render_slot' template = 'slot/slot.html' options = Options(MultiValueArgument('keys', required=False, resolve=True), ) def get_context(self, context, keys): if keys and isinstance(keys[0], models.Slot): slot = keys[0] else: key = get_key(context, keys) slot, created = models.Slot.objects.get_or_create(key=key) context.update({"slot": slot}) return context
class RenderGetPlaceholder(Placeholder): """ Render the content of a placeholder to a variable. Can be provided with the name of the placholder (i.e. "Header" in the case of a normal CMS page) or a template variable containing a placeholder (i.e. myentry.content in the case of an external app using a placeholder) {% get_placeholder ["string"|placeholder_var] as variable_name %} e.g. {% load extra_cms_tags %} {% get_placeholder "My Placeholder" as my_placeholder %} {% if my_placeholder %} <div> {{ my_placeholder }} </div> {% endif %} """ name = "get_placeholder" options = PlaceholderOptions( Argument('name', resolve=True), MultiValueArgument('extra_bits', required=False, resolve=False), 'as', Argument('varname', resolve=False, required=True), blocks=[ ('endplaceholder', 'nodelist'), ], ) def render_tag(self, context, name, extra_bits, varname, nodelist=None): if isinstance(name, PlaceholderModel): content = name.render(context, None) else: content = super(RenderGetPlaceholder, self).render_tag(context, name, extra_bits, nodelist) context[varname] = mark_safe(content) return "" def get_name(self): # Fix some template voodoo causing errors if isinstance(self.kwargs['name'].var, StringValue): return self.kwargs['name'].var.value.strip('"').strip("'") return self.kwargs['name'].var.var
class PlaceholderAsPlugins(Placeholder): """ Like DjangoCMS 'placeholder' but sets the list of linked plugins to a variable name instead of rendering the placeholder. """ name = "placeholder_as_plugins" options = PlaceholderOptions( Argument("name", resolve=False), "as", Argument("varname", resolve=False), MultiValueArgument("extra_bits", required=False, resolve=False), blocks=[("endplaceholder_as_plugins", "nodelist")], ) # pylint: disable=arguments-renamed,too-many-arguments def render_tag(self, context, name, varname, extra_bits, nodelist=None): return get_plugins_render_tag(context, name, varname, nodelist)
class StaticPlaceholderNode(Tag): name = 'static_placeholder' options = PlaceholderOptions(Argument('code', required=True), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endstatic_placeholder', 'nodelist'), ]) def render_tag(self, context, code, extra_bits, nodelist=None): content_renderer = context.get('cms_content_renderer') if not code or not content_renderer: # an empty string was passed in or the variable is not available in the context # OR cms_content_renderer is missing from context if nodelist: return nodelist.render(context) return '' if isinstance(code, StaticPlaceholder): static_placeholder = code else: kwargs = { 'code': code, 'defaults': { 'creation_method': StaticPlaceholder.CREATION_BY_TEMPLATE } } if 'site' in extra_bits: kwargs['site'] = Site.objects.get_current() else: kwargs['site_id__isnull'] = True static_placeholder = StaticPlaceholder.objects.get_or_create( **kwargs)[0] content = content_renderer.render_static_placeholder( static_placeholder, context=context, nodelist=nodelist, ) return content
class RenderGrid(InclusionTag): name = 'render_grid' template = 'grid/grid.html' options = Options( MultiValueArgument('keys', required=False, resolve=True), ) def get_context(self, context, keys): if keys and isinstance(keys[0], models.Grid): grid = keys[0] else: key = get_key(context, keys) grid, created = models.Grid.objects.get_or_create(key=key) context.update({ "grid": grid}) return context
class FrontEditTag(Tag): name = 'front_edit' options = Options( Argument('name', resolve=False, required=True), MultiValueArgument('extra_bits', required=False, resolve=True), blocks=[('end_front_edit', 'nodelist')], ) def render_tag(self, context, name, extra_bits, nodelist=None): hash_val = Placeholder.key_for(name, *extra_bits) cache_key = "front-edit-%s" % hash_val val = cache.get(cache_key) if val is None: try: val = Placeholder.objects.get(key=hash_val).value cache.set(cache_key, val, 3600 * 24) except Placeholder.DoesNotExist: pass if val is None and nodelist: val = nodelist.render(context) classes = ['editable'] if getattr(django_front_settings, 'DJANGO_FRONT_EXTRA_CONTAINER_CLASSES', None): classes.append( six.text_type(django_front_settings. DJANGO_FRONT_EXTRA_CONTAINER_CLASSES)) user = context.get('request', None) and context.get('request').user if django_front_settings.DJANGO_FRONT_PERMISSION(user): render = six.text_type(smart_text(val)).strip() if not strip_tags(render).strip(): classes.append('empty-editable') return '<div class="%s" id="%s">%s</div>' % ( ' '.join(classes), hash_val, render, ) return val or ''
class GetPlaceholderPlugins(Placeholder): """ A template tag that declares a placeholder and sets its plugins as a context variable instead of rendering them eg: {% get_placeholder_plugins "logo" as varname %} {% get_placeholder_plugins "logo" as varname or %} <div>No content</div> {% endget_placeholder_plugins %} This tag can typically be used in association with the block_plugin tag, to customize the way it is rendered eg: {% get_placeholder_plugins "logo" as plugins %} {% blockplugin plugins.0 %} <img src="{% thumbnail instance.picture 300x150 %}"/> {% endblockplugin %} Keyword arguments: name: the name of the placeholder varname: context variable name. Output will be added to template context as this variable instead of being returned. or: optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty Note: We must derive from the Placeholder class so that the tag is recognized as a placeholder and shown in the structure toolbar. """ name = "get_placeholder_plugins" options = PlaceholderOptions( Argument("name", resolve=False), "as", Argument("varname", resolve=False), MultiValueArgument("extra_bits", required=False, resolve=False), blocks=[("endget_placeholder_plugins", "nodelist")], ) # pylint: disable=arguments-differ,too-many-arguments def render_tag(self, context, name, varname, extra_bits, nodelist=None): return get_plugins_render_tag(context, name, varname, nodelist)
class GetParameters(Tag): """ {% raw %}{% get_parameters [except_field, ] %}{% endraw %} """ name = 'get_parameters' options = Options(MultiValueArgument('except_fields', required=False), ) def render_tag(self, context, except_fields): try: # If there's an exception (500), default context_processors may not # be called. request = context['request'] except KeyError: return context getvars = request.GET.copy() for field in except_fields: if field in getvars: del getvars[field] return getvars.urlencode()
class RenderPlaceholder(Placeholder): """ Render the content of a placeholder to a variable. {% placeholder "placeholder_name" as variable_name %} """ name = "get_placeholder" options = PlaceholderOptions( Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), 'as', Argument('varname', resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ], ) def render_tag(self, context, name, extra_bits, varname, nodelist=None): content = super(RenderPlaceholder, self).render_tag(context, name, extra_bits, nodelist) context[varname] = mark_safe(content) return ""
class Slot(InclusionTag): name = 'slot' template = 'slot/slot.html' options = Options( # MultiValueArgument("tagname"), # KeywordArgument("tagname", required=True, resolve=True), MultiValueArgument('keys', required=True, resolve=True), # blocks=[('endplaceholder_objects', 'nodelist', )], ) def get_context(self, context, keys): parts = [] for part in [k for k in keys if k]: if isinstance(part, Model): key = u"%s,%s,%d" % ( part._meta.app_label, part.__class__.__name__, part.pk) else: key = unicode(part) parts.append(key) key = u"|".join([unicode(i) for i in parts]) slot, created = models.Slot.objects.get_or_create(key=key) return {"slot": slot}
class PagePlaceholder(Placeholder): """ This template node is used to output page content and is also used in the admin to dynamically generate input fields. eg: {% page_placeholder "sidebar" page_lookup %} {% page_placeholder "sidebar" page_lookup inherit %} {% page_placeholder "sidebar" page_lookup as varname %} {% page_placeholder "sidebar" page_lookup or %} <div>No content</div> {% endpage_placeholder %} Keyword arguments: name: the name of the placeholder page_lookup: lookup argument for Page. See _get_page_by_untyped_arg() for detailed information on the allowed types and their interpretation for the page_lookup argument. inherit : optional argument which if given will result in inheriting the content of the placeholder with the same name on parent pages varname: context variable name. Output will be added to template context as this variable instead of being returned. or: optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = "page_placeholder" options = PlaceholderOptions( Argument("name", resolve=False), Argument("page_lookup"), MultiValueArgument("extra_bits", required=False, resolve=False), blocks=[("endpage_placeholder", "nodelist")], ) # pylint: disable=arguments-differ,too-many-arguments def render_tag(self, context, name, page_lookup, extra_bits, nodelist=None): validate_placeholder_name(name) request = context.get("request") if request: page = _get_page_by_untyped_arg(page_lookup, request, get_site_id(None)) toolbar = get_toolbar_from_request(request) renderer = toolbar.get_content_renderer() inherit = "inherit" in extra_bits # A placeholder is only editable on its own page editable = page == request.current_page try: content = renderer.render_page_placeholder( slot=name, context=context, inherit=inherit, page=page, nodelist=nodelist, editable=editable, ) except PlaceholderNotFound: content = "" else: content = "" if not content and nodelist: content = nodelist.render(context) if "as" in extra_bits: try: varname = extra_bits[extra_bits.index("as") + 1] except IndexError: raise template.TemplateSyntaxError( 'the "as" word should be followed by the variable name') context[varname] = content return "" return content
class StaticAlias(Tag): """ This template node is used to render Alias contents and is designed to be a replacement for the CMS Static Placeholder. eg: {% static_alias "identifier_text" %} eg: {% static_alias "identifier_text" site %} Keyword arguments: static_code -- the unique identifier of the Alias site -- If site is supplied an Alias instance will be created per site. """ name = 'static_alias' options = PlaceholderOptions( Argument('static_code', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endstatic_alias', 'nodelist'), ], ) def _get_alias(self, request, static_code, extra_bits): alias_filter_kwargs = { 'static_code': static_code, } # Site current_site = get_current_site() if 'site' in extra_bits: alias_filter_kwargs['site'] = current_site else: alias_filter_kwargs['site_id__isnull'] = True # Try and find an Alias to render alias = Alias.objects.filter(**alias_filter_kwargs).first() # If there is no alias found we need to create one if not alias: # If versioning is enabled we can only create the records with a logged in user / staff member if is_versioning_enabled() and not request.user.is_authenticated: return None language = get_default_language_for_site(current_site) # Parlers get_or_create doesn't work well with translations, so we must perform our own get or create default_category = Category.objects.filter(translations__name=DEFAULT_STATIC_ALIAS_CATEGORY_NAME).first() if not default_category: default_category = Category.objects.create(name=DEFAULT_STATIC_ALIAS_CATEGORY_NAME) alias_creation_kwargs = { 'static_code': static_code, 'creation_method': Alias.CREATION_BY_TEMPLATE } # Site if 'site' in extra_bits: alias_creation_kwargs['site'] = current_site alias = Alias.objects.create(category=default_category, **alias_creation_kwargs) alias_content = AliasContent.objects.create( alias=alias, name=static_code, language=language, ) if is_versioning_enabled(): from djangocms_versioning.models import Version Version.objects.create(content=alias_content, created_by=request.user) return alias def render_tag(self, context, static_code, extra_bits, nodelist=None): request = context.get('request') if not static_code or not request: # an empty string was passed in or the variable is not available in the context if nodelist: return nodelist.render(context) return '' validate_placeholder_name(static_code) toolbar = get_toolbar_from_request(request) renderer = toolbar.get_content_renderer() alias = self._get_alias(request, static_code, extra_bits) if not alias: return '' # Get draft contents in edit or preview mode? get_draft_content = False if toolbar.edit_mode_active or toolbar.preview_mode_active: get_draft_content = True language = get_language_from_request(request) placeholder = alias.get_placeholder(language=language, show_draft_content=get_draft_content) if placeholder: content = renderer.render_placeholder( placeholder=placeholder, context=context, nodelist=nodelist, ) return content return ''
class Placeholder(Tag): """ This template node is used to output page content and is also used in the admin to dynamically generate input fields. eg: {% placeholder "placeholder_name" %} {% placeholder "sidebar" inherit %} {% placeholder "footer" inherit or %} <a href="/about/">About us</a> {% endplaceholder %} Keyword arguments: name -- the name of the placeholder inherit -- optional argument which if given will result in inheriting the content of the placeholder with the same name on parent pages or -- optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = 'placeholder' options = PlaceholderOptions( Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ], ) def render_tag(self, context, name, extra_bits, nodelist=None): request = context.get('request') if not request: return '' validate_placeholder_name(name) toolbar = get_toolbar_from_request(request) renderer = toolbar.get_content_renderer() inherit = 'inherit' in extra_bits try: content = renderer.render_page_placeholder( slot=name, context=context, inherit=inherit, nodelist=nodelist, ) except PlaceholderNotFound: content = '' if not content and nodelist: return nodelist.render(context) return content def get_declaration(self): flags = self.kwargs['extra_bits'] slot = self.kwargs['name'].var.value.strip('"').strip("'") if isinstance(flags, ListValue): inherit = any(extra.var.value.strip() == 'inherit' for extra in flags) return DeclaredPlaceholder(slot=slot, inherit=inherit) return DeclaredPlaceholder(slot=slot, inherit=False)
class Placeholder(Tag): """ This template node is used to output page content and is also used in the admin to dynamically generate input fields. eg: {% placeholder "placeholder_name" %} {% placeholder "sidebar" inherit %} {% placeholder "footer" inherit or %} <a href="/about/">About us</a> {% endplaceholder %} Keyword arguments: name -- the name of the placeholder width -- additional width attribute (integer) which gets added to the plugin context (deprecated, use `{% with 320 as width %}{% placeholder "foo"}{% endwith %}`) inherit -- optional argument which if given will result in inheriting the content of the placeholder with the same name on parent pages or -- optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty """ name = 'placeholder' options = PlaceholderOptions(Argument('name', resolve=False), MultiValueArgument('extra_bits', required=False, resolve=False), blocks=[ ('endplaceholder', 'nodelist'), ]) def render_tag(self, context, name, extra_bits, nodelist=None): validate_placeholder_name(name) width = None inherit = False for bit in extra_bits: if bit == 'inherit': inherit = True elif bit.isdigit(): width = int(bit) import warnings warnings.warn( "The width parameter for the placeholder tag is deprecated.", DeprecationWarning) if not 'request' in context: return '' request = context['request'] if width: context.update({'width': width}) page = request.current_page if not page or page == 'dummy': if nodelist: return nodelist.render(context) return '' content = get_placeholder_content(context, request, page, name, inherit) if not content and nodelist: return nodelist.render(context) return content def get_name(self): return self.kwargs['name'].var.value.strip('"').strip("'")
class GetPlaceholderPlugins(Placeholder): """ A template tag that declares a placeholder and sets its plugins as a context variable instead of rendering them eg: {% get_placeholder_plugins "logo" as varname %} {% get_placeholder_plugins "logo" page_lookup as varname %} {% get_placeholder_plugins "logo" page_lookup as varname or %} <div>No content</div> {% endget_placeholder_plugins %} This tag can typically be used in association with the block_plugin tag, in a placeholder limited to one plugin, to customize the way it is rendered eg: {% get_placeholder_plugins "logo" page_lookup as plugins %} {% blockplugin plugins.0 %} <img src="{% thumbnail instance.picture 300x150 %}"/> {% endblockplugin %} Keyword arguments: name: the name of the placeholder page_lookup[optional]: lookup argument for Page. See `_get_page_by_untyped_arg()` for detailed information on the allowed types and their interpretation for the `page_lookup` argument. varname: context variable name. Output will be added to template context as this variable instead of being returned. or: optional argument which if given will make the template tag a block tag whose content is shown if the placeholder is empty Note: We must derive from the Placeholder class so that the tag is recognized as a placeholder and shown in the structure toolbar. """ name = "get_placeholder_plugins" options = PlaceholderOptions( Argument("name", resolve=False), Argument("page_lookup", required=False), "as", Argument("varname", resolve=False), MultiValueArgument("extra_bits", required=False, resolve=False), blocks=[("endget_placeholder_plugins", "nodelist")], ) # pylint: disable=arguments-differ,too-many-arguments def render_tag(self, context, name, page_lookup, varname, extra_bits, nodelist=None): """ Retrieves the placeholder's plugins and set them as a variable in the template context. If the placeholder is empty, render the block as fallback content and return the resulting HTML. If the placholder is editable, the edit script and markup are added to the HTML content. """ content = "" request = context.get("request") if request: page = _get_page_by_untyped_arg(page_lookup, request, get_site_id(None)) try: placeholder = page.placeholders.get(slot=name) except ObjectDoesNotExist: context[varname] = [] return "" else: context[varname] = [ cms_plugin.get_plugin_instance()[0] for cms_plugin in get_plugins( request, placeholder, template=page.get_template()) ] # Default content if there is no plugins in the placeholder if not context[varname] and nodelist: content = nodelist.render(context) # Add the edit script and markup to the content, only if the placeholder is editable # and the visited page is the one on which the placeholder is declared. toolbar = get_toolbar_from_request(request) if placeholder.page == request.current_page and toolbar.edit_mode_active: renderer = toolbar.get_content_renderer() data = renderer.get_editable_placeholder_context(placeholder, page=page) data["content"] = content content = renderer.placeholder_edit_template.format(**data) return content