def render_placeholder(self, placeholder, parent_object=None, template_name=None, cachable=None, limit_parent_language=True, fallback_language=None): """ The main rendering sequence for placeholders. This will do all the magic for caching, and call :func:`render_items` in the end. """ placeholder_name = get_placeholder_debug_name(placeholder) logger.debug("Rendering placeholder '%s'", placeholder_name) # Determine whether the placeholder can be cached. cachable = self._can_cache_merged_output(template_name, cachable) try_cache = cachable and self.may_cache_placeholders() logger.debug("- try_cache=%s cachable=%s template_name=%s", try_cache, cachable, template_name) if parent_object is None: # To support filtering the placeholders by parent language, the parent object needs to be known. # Fortunately, the PlaceholderFieldDescriptor makes sure this doesn't require an additional query. parent_object = placeholder.parent # Fetch the placeholder output from cache. language_code = get_parent_language_code(parent_object) cache_key = None output = None if try_cache: cache_key = get_placeholder_cache_key_for_parent( parent_object, placeholder.slot, language_code) output = cache.get(cache_key) if output: logger.debug("- fetched cached output") if output is None: # Get the items, and render them items, is_fallback = self._get_placeholder_items( placeholder, parent_object, limit_parent_language, fallback_language, try_cache) output = self.render_items(placeholder, items, parent_object, template_name, cachable) if is_fallback: # Caching fallbacks is not supported yet, # content could be rendered in a different gettext language domain. output.cacheable = False # Store the full-placeholder contents in the cache. if try_cache and output.cacheable: if output.cache_timeout is not DEFAULT_TIMEOUT: # The timeout is based on the minimal timeout used in plugins. cache.set(cache_key, output, output.cache_timeout) else: # Don't want to mix into the default 0/None issue. cache.set(cache_key, output) return output
def get_cached_placeholder_output(parent_object, placeholder_name): """ Return cached output for a placeholder, if available. This avoids fetching the Placeholder object. """ if not appsettings.FLUENT_CONTENTS_CACHE_OUTPUT or not appsettings.FLUENT_CONTENTS_CACHE_PLACEHOLDER_OUTPUT: return None language_code = get_parent_language_code(parent_object) cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder_name, language_code) return cache.get(cache_key)
def __init__(self, *args, **kwargs): instance = kwargs['instance'] if instance: self.current_language = get_parent_language_code(instance) if self.current_language and 'queryset' in kwargs: kwargs['queryset'] = kwargs['queryset'].filter(language_code=self.current_language) else: self.current_language = appsettings.FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE super(BaseContentItemFormSet, self).__init__(*args, **kwargs) self._deleted_placeholders = () # internal property, set by PlaceholderEditorAdmin
def get_cached_placeholder_output(parent_object, placeholder_name): """ Return cached output for a placeholder, if available. This avoids fetching the Placeholder object. """ if not PlaceholderRenderingPipe.may_cache_placeholders(): return None language_code = get_parent_language_code(parent_object) cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder_name, language_code) return cache.get(cache_key)
def get_cached_placeholder_output(parent_object, placeholder_name): """ Return cached output for a placeholder, if available. This avoids fetching the Placeholder object. """ if not appsettings.FLUENT_CONTENTS_CACHE_OUTPUT \ or not appsettings.FLUENT_CONTENTS_CACHE_PLACEHOLDER_OUTPUT: return None language_code = get_parent_language_code(parent_object) cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder_name, language_code) return cache.get(cache_key)
def render_placeholder(self, placeholder, parent_object=None, template_name=None, cachable=None, limit_parent_language=True, fallback_language=None): """ The main rendering sequence for placeholders. This will do all the magic for caching, and call :func:`render_items` in the end. """ placeholder_name = get_placeholder_debug_name(placeholder) logger.debug("Rendering placeholder '%s'", placeholder_name) # Determine whether the placeholder can be cached. cachable = self._can_cache_merged_output(template_name, cachable) try_cache = cachable and self.may_cache_placeholders() logger.debug("- try_cache=%s cachable=%s template_name=%s", try_cache, cachable, template_name) if parent_object is None: # To support filtering the placeholders by parent language, the parent object needs to be known. # Fortunately, the PlaceholderFieldDescriptor makes sure this doesn't require an additional query. parent_object = placeholder.parent # Fetch the placeholder output from cache. language_code = get_parent_language_code(parent_object) cache_key = None output = None if try_cache: cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder.slot, language_code) output = cache.get(cache_key) if output: logger.debug("- fetched cached output") if output is None: # Get the items, and render them items, is_fallback = self._get_placeholder_items(placeholder, parent_object, limit_parent_language, fallback_language, try_cache) output = self.render_items(placeholder, items, parent_object, template_name, cachable) if is_fallback: # Caching fallbacks is not supported yet, # content could be rendered in a different gettext language domain. output.cacheable = False # Store the full-placeholder contents in the cache. if try_cache and output.cacheable: if output.cache_timeout is not DEFAULT_TIMEOUT: # The timeout is based on the minimal timeout used in plugins. cache.set(cache_key, output, output.cache_timeout) else: # Don't want to mix into the default 0/None issue. cache.set(cache_key, output) return output
def render_placeholder_search_text(placeholder, fallback_language=None): """ Render a :class:`~fluent_contents.models.Placeholder` object to search text. This text can be used by an indexer (e.g. haystack) to produce content search for a parent object. :param placeholder: The placeholder object. :type placeholder: :class:`~fluent_contents.models.Placeholder` :param fallback_language: The fallback language to use if there are no items in the current language. Passing ``True`` uses the default :ref:`FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE`. :type fallback_language: bool|str :rtype: str """ parent_object = placeholder.parent # this is a cached lookup thanks to PlaceholderFieldDescriptor language = get_parent_language_code(parent_object) output = SearchRenderingPipe(language).render_placeholder( placeholder=placeholder, parent_object=parent_object, fallback_language=fallback_language) return output.html # Tags already stripped.
def render(self, name, value, attrs=None): """ Render the placeholder field. """ other_instance_languages = None if value and value != "-DUMMY-": parent = Placeholder.objects.get(pk=long(value)).parent language_code = get_parent_language_code(parent) if language_code: # Parent is a multilingual object, provide information for the copy dialog. other_instance_languages = get_parent_active_language_choices(parent, exclude_current=True) context = { 'cp_plugin_list': list(self.plugins), 'placeholder_id': '', 'placeholder_slot': self.slot, 'other_instance_languages': other_instance_languages, } return mark_safe(render_to_string('admin/fluent_contents/placeholderfield/widget.html', context))
def render_placeholder_search_text(placeholder, fallback_language=None): """ Render a :class:`~fluent_contents.models.Placeholder` object to search text. This text can be used by an indexer (e.g. haystack) to produce content search for a parent object. :param placeholder: The placeholder object. :type placeholder: :class:`~fluent_contents.models.Placeholder` :param fallback_language: The fallback language to use if there are no items in the current language. Passing ``True`` uses the default :ref:`FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE`. :type fallback_language: bool|str :rtype: str """ parent_object = placeholder.parent # this is a cached lookup thanks to PlaceholderFieldDescriptor language = get_parent_language_code(parent_object) output = SearchRenderingPipe(language).render_placeholder( placeholder=placeholder, parent_object=parent_object, fallback_language=fallback_language ) return output.html # Tags already stripped.
def render_placeholder( request, placeholder, parent_object=None, template_name=None, cachable=None, limit_parent_language=True, fallback_language=None, ): """ Render a :class:`~fluent_contents.models.Placeholder` object. Returns a :class:`~fluent_contents.models.ContentItemOutput` object which contains the HTML output and :class:`~django.forms.Media` object. This function also caches the complete output of the placeholder when all individual items are cacheable. :param request: The current request object. :type request: :class:`~django.http.HttpRequest` :param placeholder: The placeholder object. :type placeholder: :class:`~fluent_contents.models.Placeholder` :param parent_object: Optional, the parent object of the placeholder (already implied by the placeholder) :param template_name: Optional template name used to concatenate the placeholder output. :type template_name: str | None :param cachable: Whether the output is cachable, otherwise the full output will not be cached. Default: False when using a template, True otherwise. :type cachable: bool | None :param limit_parent_language: Whether the items should be limited to the parent language. :type limit_parent_language: bool :param fallback_language: The fallback language to use if there are no items in the current language. Passing ``True`` uses the default :ref:`FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE`. :type fallback_language: bool/str :rtype: :class:`~fluent_contents.models.ContentItemOutput` """ _optimize_logger() placeholder_name = _get_placeholder_name(placeholder) logger.debug("Rendering placeholder '%s'", placeholder_name) if cachable is None: # default: True unless there is a template. cachable = not bool(template_name) # Caching will not happen when rendering via a template, # because there is no way to tell whether that can be expired/invalidated. try_cache = ( appsettings.FLUENT_CONTENTS_CACHE_OUTPUT and appsettings.FLUENT_CONTENTS_CACHE_PLACEHOLDER_OUTPUT and cachable ) cache_key = None output = None logger.debug("- try_cache=%s cachable=%s template_name=%s", try_cache, cachable, template_name) if parent_object is None: # To support filtering the placeholders by parent language, the parent object needs to be known. # Fortunately, the PlaceholderFieldDescriptor makes sure this doesn't require an additional query. parent_object = placeholder.parent language_code = get_parent_language_code(parent_object) if try_cache: cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder.slot, language_code) output = cache.get(cache_key) if output is None: # No full-placeholder cache. Get the items items = placeholder.get_content_items( parent_object, limit_parent_language=limit_parent_language ).non_polymorphic() if _LOG_DEBUG and is_queryset_empty(items): # Detect qs.none() was applied logging.debug("- skipping regular language, parent object has no translation for it.") if fallback_language and not items: # NOTES: performs query, so hence the .non_polymorphic() above # There are no items, but there is a fallback option. # This is not supported yet, content can be rendered in a different gettext language domain. try_cache = False language_code = ( appsettings.FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE if fallback_language is True else fallback_language ) logger.debug("- reading fallback language %s, try_cache=%s", language_code, try_cache) items = ( placeholder.get_content_items(parent_object, limit_parent_language=False) .translated(language_code) .non_polymorphic() ) output = _render_items( request, placeholder, items, parent_object=parent_object, template_name=template_name, cachable=cachable ) # Store the full-placeholder contents in the cache. if try_cache and output.cacheable and cache_key is not None: # The timeout takes notice of the minimal timeout used in plugins. if output.cache_timeout is not DEFAULT_TIMEOUT: cache.set(cache_key, output, output.cache_timeout) else: # Don't want to mix into the default 0/None issue. cache.set(cache_key, output) else: logger.debug("- fetched cached output") if is_edit_mode(request): output.html = _wrap_placeholder_output(output.html, placeholder) return output
def render_placeholder(request, placeholder, parent_object=None, template_name=None, template_cachable=False, limit_parent_language=True, fallback_language=None): """ Render a :class:`~fluent_contents.models.Placeholder` object. Returns a :class:`~fluent_contents.models.ContentItemOutput` object which contains the HTML output and :class:`~django.forms.Media` object. This function also caches the complete output of the placeholder when all individual items are cacheable. :param request: The current request object. :type request: :class:`~django.http.HttpRequest` :param placeholder: The placeholder object. :type placeholder: :class:`~fluent_contents.models.Placeholder` :param parent_object: Optional, the parent object of the placeholder (already implied by the placeholder) :param template_name: Optional template name used to concatenate the placeholder output. :type template_name: str | None :param template_cachable: Whether the provided template is cachable, otherwise the full output will not be cached. :type template_cachable: bool :param limit_parent_language: Whether the items should be limited to the parent language. :type limit_parent_language: bool :param fallback_language: The fallback language to use if there are no items in the current language. Passing ``True`` uses the default :ref:`FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE`. :type fallback_language: bool/str :rtype: :class:`~fluent_contents.models.ContentItemOutput` """ # Caching will not happen when rendering via a template, # because there is no way to tell whether that can be expired/invalidated. try_cache = appsettings.FLUENT_CONTENTS_CACHE_OUTPUT \ and appsettings.FLUENT_CONTENTS_CACHE_PLACEHOLDER_OUTPUT \ and (not template_name or template_cachable) cache_key = None output = None if parent_object is None: # To support filtering the placeholders by parent language, the parent object needs to be known. # Fortunately, the PlaceholderFieldDescriptor makes sure this doesn't require an additional query. parent_object = placeholder.parent language_code = get_parent_language_code(parent_object) if try_cache: cache_key = get_placeholder_cache_key_for_parent(parent_object, placeholder.slot, language_code) output = cache.get(cache_key) if output is None: # No full-placeholder cache. Get the items items = placeholder.get_content_items(parent_object, limit_parent_language=limit_parent_language).non_polymorphic() if fallback_language \ and not items: # NOTES: performs query, so hence the .non_polymorphic() above # There are no items, but there is a fallback option. try_cache = False # This is not supported yet, content can be rendered in a different gettext language domain. language_code = appsettings.FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE if fallback_language is True else fallback_language items = placeholder.get_content_items(parent_object, limit_parent_language=False).translated(language_code).non_polymorphic() output = _render_items(request, placeholder, items, parent_object=parent_object, template_name=template_name, template_cachable=template_cachable) # Store the full-placeholder contents in the cache. if try_cache and output.cacheable and cache_key is not None: cache.set(cache_key, output) if is_edit_mode(request): output.html = _wrap_placeholder_output(output.html, placeholder) return output
def render_placeholder(request, placeholder, parent_object=None, template_name=None, cachable=None, limit_parent_language=True, fallback_language=None): """ Render a :class:`~fluent_contents.models.Placeholder` object. Returns a :class:`~fluent_contents.models.ContentItemOutput` object which contains the HTML output and :class:`~django.forms.Media` object. This function also caches the complete output of the placeholder when all individual items are cacheable. :param request: The current request object. :type request: :class:`~django.http.HttpRequest` :param placeholder: The placeholder object. :type placeholder: :class:`~fluent_contents.models.Placeholder` :param parent_object: Optional, the parent object of the placeholder (already implied by the placeholder) :param template_name: Optional template name used to concatenate the placeholder output. :type template_name: str | None :param cachable: Whether the output is cachable, otherwise the full output will not be cached. Default: False when using a template, True otherwise. :type cachable: bool | None :param limit_parent_language: Whether the items should be limited to the parent language. :type limit_parent_language: bool :param fallback_language: The fallback language to use if there are no items in the current language. Passing ``True`` uses the default :ref:`FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE`. :type fallback_language: bool/str :rtype: :class:`~fluent_contents.models.ContentItemOutput` """ _optimize_logger() placeholder_name = _get_placeholder_name(placeholder) logger.debug("Rendering placeholder '%s'", placeholder_name) if cachable is None: # default: True unless there is a template. cachable = not bool(template_name) # Caching will not happen when rendering via a template, # because there is no way to tell whether that can be expired/invalidated. try_cache = appsettings.FLUENT_CONTENTS_CACHE_OUTPUT \ and appsettings.FLUENT_CONTENTS_CACHE_PLACEHOLDER_OUTPUT \ and cachable cache_key = None output = None logger.debug("- try_cache=%s cachable=%s template_name=%s", try_cache, cachable, template_name) if parent_object is None: # To support filtering the placeholders by parent language, the parent object needs to be known. # Fortunately, the PlaceholderFieldDescriptor makes sure this doesn't require an additional query. parent_object = placeholder.parent language_code = get_parent_language_code(parent_object) if try_cache: cache_key = get_placeholder_cache_key_for_parent( parent_object, placeholder.slot, language_code) output = cache.get(cache_key) if output is None: # No full-placeholder cache. Get the items items = placeholder.get_content_items( parent_object, limit_parent_language=limit_parent_language).non_polymorphic() if _LOG_DEBUG and is_queryset_empty( items): # Detect qs.none() was applied logging.debug( "- skipping regular language, parent object has no translation for it." ) if fallback_language \ and not items: # NOTES: performs query, so hence the .non_polymorphic() above # There are no items, but there is a fallback option. # This is not supported yet, content can be rendered in a different gettext language domain. try_cache = False language_code = appsettings.FLUENT_CONTENTS_DEFAULT_LANGUAGE_CODE if fallback_language is True else fallback_language logger.debug("- reading fallback language %s, try_cache=%s", language_code, try_cache) items = placeholder.get_content_items( parent_object, limit_parent_language=False).translated( language_code).non_polymorphic() output = _render_items(request, placeholder, items, parent_object=parent_object, template_name=template_name, cachable=cachable) # Store the full-placeholder contents in the cache. if try_cache and output.cacheable and cache_key is not None: # The timeout takes notice of the minimal timeout used in plugins. if output.cache_timeout is not DEFAULT_TIMEOUT: cache.set(cache_key, output, output.cache_timeout) else: # Don't want to mix into the default 0/None issue. cache.set(cache_key, output) else: logger.debug("- fetched cached output") if is_edit_mode(request): output.html = _wrap_placeholder_output(output.html, placeholder) return output