def _get_title_cache(self, language, fallback, force_reload): if not language: language = get_language() load = False if not hasattr(self, 'title_cache') or force_reload: load = True self.title_cache = {} elif language not in self.title_cache: if fallback: fallback_langs = i18n.get_fallback_languages(language) for lang in fallback_langs: if lang in self.title_cache: return lang load = True if load: from .title import Title titles = Title.objects.filter(article=self) for title in titles: self.title_cache[title.language] = title if language in self.title_cache: return language else: if fallback: fallback_langs = i18n.get_fallback_languages(language) for lang in fallback_langs: if lang in self.title_cache: return lang return language
def get_current_page(path, lang, queryset, home_slug, home_tree_id): """Helper for getting current page from path depending on language returns: (Page, None) or (None, path_to_alternative language) """ try: if home_slug: queryset = queryset.exclude(Q(title_set__path=home_slug)&Q(tree_id=home_tree_id)) home_slug += "/" title_q = Q(title_set__path=path)|(Q(title_set__path=home_slug + path)&Q(tree_id=home_tree_id)) else: title_q = Q(title_set__slug=path) if settings.CMS_FLAT_URLS: return queryset.filter(title_q & Q(title_set__language=lang)).distinct().select_related()[0], None else: page = queryset.filter(title_q).distinct().select_related()[0] if page: langs = page.get_languages() if lang in langs: return page, None else: path = None for alt_lang in get_fallback_languages(lang): if alt_lang in langs: path = '/%s%s' % (alt_lang, page.get_absolute_url(language=lang, fallback=True)) return None, path return None, path except IndexError: return None, None
def assign_plugins(request, placeholders, lang=None): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ placeholders = list(placeholders) if not placeholders: return lang = lang or get_language_from_request(request) request_lang = lang if hasattr(request, "current_page") and request.current_page is not None: languages = request.current_page.get_languages() if not lang in languages and not get_redirect_on_fallback(lang): fallbacks = get_fallback_languages(lang) for fallback in fallbacks: if fallback in languages: request_lang = fallback break # get all plugins for the given placeholders qs = get_cmsplugin_queryset(request).filter(placeholder__in=placeholders, language=request_lang).order_by( 'placeholder', 'tree_id', 'lft') plugin_list = downcast_plugins(qs) # split the plugins up by placeholder groups = dict((key, list(plugins)) for key, plugins in groupby(plugin_list, operator.attrgetter('placeholder_id'))) for group in groups: groups[group] = build_plugin_tree(groups[group]) for placeholder in placeholders: setattr(placeholder, '_%s_plugins_cache' % lang, list(groups.get(placeholder.pk, [])))
def get_fallback_language(language): try: language_list = get_fallback_languages(language) if len(language_list) > 0: return language_list[0] except: return None
def get_nodes(self, request): page_queryset = get_page_queryset(request) site = current_site(request) lang = get_language_from_request(request) filters = { 'site': site, } if hide_untranslated(lang, site.pk): filters['title_set__language'] = lang if not use_draft(request): filters['title_set__published'] = True if not use_draft(request): page_queryset = page_queryset.published() pages = page_queryset.filter(**filters).order_by("path") ids = {} nodes = [] first = True home_cut = False home_children = [] home = None actual_pages = [] # cache view perms visible_pages = get_visible_pages(request, pages, site) for page in pages: # Pages are ordered by path, therefore the first page is the root # of the page tree (a.k.a "home") if page.pk not in visible_pages: # Don't include pages the user doesn't have access to continue if not home: home = page if first and page.pk != home.pk: home_cut = True if (home_cut and (page.parent_id == home.pk or page.parent_id in home_children)): home_children.append(page.pk) if ((page.pk == home.pk and home.in_navigation) or page.pk != home.pk): first = False ids[page.id] = page actual_pages.append(page) page.title_cache = {} langs = [lang] if not hide_untranslated(lang): langs.extend(get_fallback_languages(lang)) titles = list(get_title_queryset(request).filter( page__in=ids, language__in=langs)) for title in titles: # add the title and slugs and some meta data page = ids[title.page_id] page.title_cache[title.language] = title for page in actual_pages: if page.title_cache: nodes.append(page_to_node(page, home, home_cut)) return nodes
def _get_title_cache(self, language, fallback, version_id, force_reload): if not language: language = get_language() load = False if not hasattr(self, "title_cache") or force_reload: load = True self.title_cache = {} elif not language in self.title_cache: if fallback: fallback_langs = get_fallback_languages(language) for lang in fallback_langs: if lang in self.title_cache: return lang load = True if load: from cms.models.titlemodels import Title if version_id: from reversion.models import Version version = get_object_or_404(Version, pk=version_id) revs = [related_version.object_version for related_version in version.revision.version_set.all()] for rev in revs: obj = rev.object if obj.__class__ == Title: self.title_cache[obj.language] = obj else: title = Title.objects.get_title(self, language, language_fallback=fallback) if title: self.title_cache[title.language] = title language = title.language return language
def assign_plugins(request, placeholders, template, lang=None, no_fallback=False): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ placeholders = list(placeholders) if not placeholders: return lang = lang or get_language_from_request(request) request_lang = lang qs = get_cmsplugin_queryset(request).filter( placeholder__in=placeholders, language=request_lang).order_by('placeholder', 'tree_id', 'level', 'position') plugins = list(qs) # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if not no_fallback: for placeholder in placeholders: found = False for plugin in plugins: if plugin.placeholder_id == placeholder.pk: found = True break if found: continue elif placeholder and get_placeholder_conf( "language_fallback", placeholder.slot, template, False): fallbacks = get_fallback_languages(lang) for fallback_language in fallbacks: assign_plugins(request, [placeholder], template, fallback_language, no_fallback=True) plugins = placeholder._plugins_cache if plugins: break # If no plugin is present, create default plugins if enabled) if not plugins: plugins = create_default_plugins(request, placeholders, template, lang) plugin_list = downcast_plugins(plugins, placeholders) # split the plugins up by placeholder groups = dict((key, list(plugins)) for key, plugins in groupby( plugin_list, operator.attrgetter('placeholder_id'))) for group in groups: groups[group] = build_plugin_tree(groups[group]) for placeholder in placeholders: setattr(placeholder, '_plugins_cache', list(groups.get(placeholder.pk, [])))
def get_nodes(self, request): page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) filters = { 'site': site, } if hide_untranslated(lang, site.pk): filters['title_set__language'] = lang if not use_draft(request): page_queryset = page_queryset.published(lang) pages = page_queryset.filter(**filters).order_by("tree_id", "lft") ids = {} nodes = [] first = True home_cut = False home_children = [] home = None actual_pages = [] # cache view perms visible_pages = get_visible_pages(request, pages, site) for page in pages: # Pages are ordered by tree_id, therefore the first page is the root # of the page tree (a.k.a "home") if page.pk not in visible_pages: # Don't include pages the user doesn't have access to continue if not home: home = page if first and page.pk != home.pk: home_cut = True if (page.parent_id == home.pk or page.parent_id in home_children) and home_cut: home_children.append(page.pk) if (page.pk == home.pk and home.in_navigation) or page.pk != home.pk: first = False ids[page.id] = page actual_pages.append(page) page.title_cache = {} langs = [lang] if not hide_untranslated(lang): langs.extend(get_fallback_languages(lang)) titles = list(get_title_queryset(request).filter(page__in=ids, language__in=langs)) for title in titles: # add the title and slugs and some meta data page = ids[title.page_id] page.title_cache[title.language] = title for page in actual_pages: if page.title_cache: nodes.append(page_to_node(page, home, home_cut)) return nodes
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'] lang = get_language_from_request(request) plugins = [plugin for plugin in get_plugins(request, placeholder)] if not plugins and settings.CMS_LANGUAGE_FALLBACK and lang != get_default_language(): fallbacks = get_fallback_languages(lang) for l in fallbacks: plugins = [plugin for plugin in get_plugins(request, placeholder, l)] if plugins: break 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(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'] lang = get_language_from_request(request) page = get_page_from_placeholder_if_exists(placeholder) if page: template = page.template else: template = None plugins = [plugin for plugin in get_plugins(request, placeholder, lang)] if (len(plugins)==0 and placeholder and lang != get_default_language() and get_placeholder_conf("language_fallback", placeholder.slot, template, False)): fallbacks = get_fallback_languages(lang) for l in fallbacks: plugins = [plugin for plugin in get_plugins(request, placeholder, l)] if plugins: break # 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 content = [] # 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 content.extend(render_plugins(plugins, context, placeholder, processors)) content = "".join(content) if edit: content = render_placeholder_toolbar(placeholder, context, content, name_fallback) context.pop() return content
def get_nodes(self, request): page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) filters = { 'site':site, } if settings.CMS_HIDE_UNTRANSLATED: filters['title_set__language'] = lang pages = page_queryset.published().filter(**filters).order_by("tree_id", "lft") ids = [] nodes = [] first = True home_cut = False home_children = [] home = None for page in pages: if not home: home = page page.home_pk_cache = home.pk if first and page.pk != home.pk: home_cut = True if (page.parent_id == home.pk or page.parent_id in home_children) and home_cut: page.home_cut_cache = True home_children.append(page.pk) if (page.pk == home.pk and home.in_navigation) or page.pk != home.pk: first = False ids.append(page.id) titles = list(get_title_queryset(request).filter(page__in=ids, language=lang)) for page in pages:# add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) if ids: # get fallback languages fallbacks = get_fallback_languages(lang) for l in fallbacks: titles = list(get_title_queryset(request).filter(page__in=ids, language=l)) for title in titles: for page in pages:# add the title and slugs and some meta data if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) break if not ids: break return nodes
def assign_plugins(request, placeholders, template, lang=None, is_fallback=False): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ if not placeholders: return placeholders = tuple(placeholders) lang = lang or get_language_from_request(request) qs = get_cmsplugin_queryset(request) qs = qs.filter(placeholder__in=placeholders, language=lang) plugins = list(qs.order_by('placeholder', 'path')) fallbacks = defaultdict(list) # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if (not is_fallback and not (hasattr(request, 'toolbar') and request.toolbar.edit_mode)): disjoint_placeholders = (ph for ph in placeholders if all( ph.pk != p.placeholder_id for p in plugins)) for placeholder in disjoint_placeholders: if get_placeholder_conf("language_fallback", placeholder.slot, template, True): for fallback_language in get_fallback_languages(lang): assign_plugins(request, (placeholder, ), template, fallback_language, is_fallback=True) fallback_plugins = placeholder._plugins_cache if fallback_plugins: fallbacks[placeholder.pk] += fallback_plugins break # These placeholders have no fallback non_fallback_phs = [ph for ph in placeholders if ph.pk not in fallbacks] # If no plugin is present in non fallback placeholders, create default plugins if enabled) if not plugins: plugins = create_default_plugins(request, non_fallback_phs, template, lang) plugins = downcast_plugins(plugins, non_fallback_phs) # split the plugins up by placeholder # Plugins should still be sorted by placeholder plugin_groups = dict( (key, list(plugins)) for key, plugins in groupby(plugins, attrgetter('placeholder_id'))) for group in plugin_groups: plugin_groups[group] = build_plugin_tree(plugin_groups[group]) groups = fallbacks.copy() groups.update(plugin_groups) for placeholder in placeholders: setattr(placeholder, '_plugins_cache', groups.get(placeholder.pk, []))
def __getattr__(self, attr): current_lang = get_language() lang_attr = attr + '_' + current_lang if lang_attr in self.__dict__: return self.__dict__[lang_attr] for lang in get_fallback_languages(current_lang): lang_attr = attr + '_' + lang if lang_attr in self.__dict__: return self.__dict__[lang_attr] # secondary_attrs=self.get_secondary_attributes() # if attr in secondary_attrs: # return getattr(self.eav, attr) # # lang_attr=attr+'_'+current_lang # if lang_attr in secondary_attrs: # return getattr(self.eav, lang_attr) # # for lang in get_fallback_languages(current_lang): # lang_attr=attr+'_'+lang # if lang_attr in secondary_attrs: # return getattr(self.eav, lang_attr) if attr == '_position_in_list_cache': #for position field raise AttributeError if attr[-2:] == '_m': lang_attr = attr[:-2] + '_' + current_lang try: return getattr(self.eav, lang_attr) except AttributeError: for lang in get_fallback_languages(current_lang): lang_attr = attr[:-2] + '_' + lang try: return getattr(self.eav, lang_attr) except AttributeError: pass return '' else: return getattr(self.eav, attr)
def get_teaser(self, language=None, fallback=True, version_id=None, force_reload=False): """ Get the teaser of the page depending on the given language """ # This is based largely off of ``cms.models.Page.get_title`` # but it doesn't bother with revisions and flattens out # the logic in ``get_title_obj_attribute``, # ``get_title_obj`` and ``_get_title_cache`` into a single # method if not language: language = get_language() load = False if not hasattr(self, 'teaser_cache') or force_reload: # No teasers have been cached. We need to load the # teaser from the database load = True # But first, create the cache attribute self.teaser_cache = {} elif not language in self.teaser_cache: # We have the cache set up, but the desired language # isn't cached. if fallback: # Check if we've cached the teaser in a fallback # language fallback_langs = i18n.get_fallback_languages(language) for lang in fallback_langs: if lang in self.teaser_cache: # We found a teaser for the fallback # language. Return it! return self.teaser_cache[lang].teaser # We didn't find teasers in any fallback language, # We'll try to load it from the database below load = True if load: # Use ``TeaserManager.get_teaser`` to handle # getting the ``Teaser`` instance from the database # wth language fallback teaser = Teaser.objects.get_teaser(self, language, language_fallback=fallback) if teaser: # We found a teaser. Cache it and then return it self.teaser_cache[teaser.language] = teaser return teaser.teaser # If all else fails, return an empty string return ""
def get_alternate(page, site=None, site_languages=None, protocol=None, enable_redirectors=None): # Optimize for repeated calls within the same site if site is None: site = Site.objects.get_current() if site_languages is None: site_languages = get_public_languages(site.pk) # TODO: build API for this default if enable_redirectors is None: enable_redirectors = get_config_redirectors() protocol = protocol if protocol is not None else 'http' # find all public translations for this page available_languages = {l for l in page.get_languages() if l in site_languages} sitemap_languages = [l for l in site_languages if l in available_languages] # handle case when hide_untranslated = False if len(sitemap_languages) < len(site_languages): for lang in site_languages: if (lang not in sitemap_languages and not hide_untranslated(lang, site.pk)): for fb_lang in sitemap_languages: if fb_lang in get_fallback_languages(lang, site.pk): sitemap_languages.append(lang) break # Append default redirector link if sitemap_languages and enable_redirectors: sitemap_languages.append(LANG_REDIRECTOR) alt_links = OrderedDict() for lang in sitemap_languages: if lang == LANG_REDIRECTOR: with override(sitemap_languages[0]): url = page.get_absolute_url() url = re.sub(r'^/{}'.format(sitemap_languages[0]), '', url) assert sitemap_languages[0] != LANG_REDIRECTOR else: with override(lang): url = page.get_absolute_url() alt_links[lang] = {'language_code': lang, 'location': '%s://%s%s' % (protocol, site.domain, url), 'redirector': lang == LANG_REDIRECTOR, 'path': url} return alt_links
def assign_plugins(request, placeholders, template, lang=None, no_fallback=False): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ placeholders = list(placeholders) if not placeholders: return lang = lang or get_language_from_request(request) request_lang = lang qs = get_cmsplugin_queryset(request).filter(placeholder__in=placeholders, language=request_lang).order_by( 'placeholder', 'tree_id', 'level', 'position') plugins = list(qs) # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if not no_fallback: for placeholder in placeholders: found = False for plugin in plugins: if plugin.placeholder_id == placeholder.pk: found = True break if found: continue elif placeholder and get_placeholder_conf("language_fallback", placeholder.slot, template, False): if hasattr(request, 'toolbar') and request.toolbar.edit_mode: continue fallbacks = get_fallback_languages(lang) for fallback_language in fallbacks: assign_plugins(request, [placeholder], template, fallback_language, no_fallback=True) fallback_plugins = placeholder._plugins_cache if fallback_plugins: plugins += fallback_plugins break # If no plugin is present, create default plugins if enabled) if not plugins: plugins = create_default_plugins(request, placeholders, template, lang) plugin_list = downcast_plugins(plugins, placeholders) # split the plugins up by placeholder groups = dict((key, list(plugins)) for key, plugins in groupby(plugin_list, operator.attrgetter('placeholder_id'))) for group in groups: groups[group] = build_plugin_tree(groups[group]) for placeholder in placeholders: setattr(placeholder, '_plugins_cache', list(groups.get(placeholder.pk, [])))
def update_site_and_page_choices(lang=None): lang = lang or i18n.get_current_language() SITE_CHOICES_KEY = get_site_cache_key(lang) PAGE_CHOICES_KEY = get_page_cache_key(lang) title_queryset = (Title.objects.drafts() .select_related('page', 'page__site') .order_by('page__tree_id', 'page__lft', 'page__rght')) pages = defaultdict(SortedDict) sites = {} for title in title_queryset: page = pages[title.page.site.pk].get(title.page.pk, {}) page[title.language] = title pages[title.page.site.pk][title.page.pk] = page sites[title.page.site.pk] = title.page.site.name site_choices = [] page_choices = [('', '----')] try: fallbacks = i18n.get_fallback_languages(lang) except LanguageError: fallbacks = [] language_order = [lang] + fallbacks for sitepk, sitename in sites.items(): site_choices.append((sitepk, sitename)) site_page_choices = [] for titles in pages[sitepk].values(): title = None for language in language_order: title = titles.get(language) if title: break if not title: continue indent = u" " * title.page.level page_title = mark_safe(u"%s%s" % (indent, title.title)) site_page_choices.append((title.page.pk, page_title)) page_choices.append((sitename, site_page_choices)) from django.core.cache import cache # We set it to 1 day here because we actively invalidate this cache. cache.set(SITE_CHOICES_KEY, site_choices, 86400) cache.set(PAGE_CHOICES_KEY, page_choices, 86400) return site_choices, page_choices
def update_site_and_page_choices(lang=None): lang = lang or translation.get_language() SITE_CHOICES_KEY = get_site_cache_key(lang) PAGE_CHOICES_KEY = get_page_cache_key(lang) if settings.CMS_MODERATOR: title_queryset = Title.objects.filter(page__publisher_is_draft=False) else: title_queryset = Title.objects.filter(page__publisher_is_draft=True) title_queryset = title_queryset.select_related( 'page', 'page__site').order_by('page__tree_id', 'page__lft', 'page__rght') pages = defaultdict(SortedDict) sites = {} for title in title_queryset: page = pages[title.page.site.pk].get(title.page.pk, {}) page[title.language] = title pages[title.page.site.pk][title.page.pk] = page sites[title.page.site.pk] = title.page.site.name site_choices = [] page_choices = [('', '----')] language_order = [lang] + i18n.get_fallback_languages(lang) for sitepk, sitename in sites.items(): site_choices.append((sitepk, sitename)) site_page_choices = [] for titles in pages[sitepk].values(): title = None for language in language_order: title = titles.get(language) if title: break if not title: continue indent = u" " * title.page.level page_title = mark_safe(u"%s%s" % (indent, title.title)) site_page_choices.append((title.page.pk, page_title)) page_choices.append((sitename, site_page_choices)) # We set it to 1 day here because we actively invalidate this cache. cache.set(SITE_CHOICES_KEY, site_choices, 86400) cache.set(PAGE_CHOICES_KEY, page_choices, 86400) return site_choices, page_choices
def update_site_and_page_choices(lang=None): lang = lang or translation.get_language() SITE_CHOICES_KEY = get_site_cache_key(lang) PAGE_CHOICES_KEY = get_page_cache_key(lang) if settings.CMS_MODERATOR: title_queryset = Title.objects.filter(page__publisher_is_draft=False) else: title_queryset = Title.objects.filter(page__publisher_is_draft=True) title_queryset = title_queryset.select_related("page", "page__site").order_by( "page__tree_id", "page__lft", "page__rght" ) pages = defaultdict(SortedDict) sites = {} for title in title_queryset: page = pages[title.page.site.pk].get(title.page.pk, {}) page[title.language] = title pages[title.page.site.pk][title.page.pk] = page sites[title.page.site.pk] = title.page.site.name site_choices = [] page_choices = [("", "----")] language_order = [lang] + i18n.get_fallback_languages(lang) for sitepk, sitename in sites.items(): site_choices.append((sitepk, sitename)) site_page_choices = [] for titles in pages[sitepk].values(): title = None for language in language_order: title = titles.get(language) if title: break if not title: continue indent = u" " * title.page.level page_title = mark_safe(u"%s%s" % (indent, title.title)) site_page_choices.append((title.page.pk, page_title)) page_choices.append((sitename, site_page_choices)) # We set it to 1 day here because we actively invalidate this cache. cache.set(SITE_CHOICES_KEY, site_choices, 86400) cache.set(PAGE_CHOICES_KEY, page_choices, 86400) return site_choices, page_choices
def assign_plugins(request, placeholders, template, lang=None, is_fallback=False): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ if not placeholders: return placeholders = tuple(placeholders) lang = lang or get_language_from_request(request) qs = get_cmsplugin_queryset(request) qs = qs.filter(placeholder__in=placeholders, language=lang) plugins = list(qs.order_by('placeholder', 'path')) fallbacks = defaultdict(list) # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if (not is_fallback and not (hasattr(request, 'toolbar') and request.toolbar.edit_mode)): disjoint_placeholders = (ph for ph in placeholders if all(ph.pk != p.placeholder_id for p in plugins)) for placeholder in disjoint_placeholders: if get_placeholder_conf("language_fallback", placeholder.slot, template, True): for fallback_language in get_fallback_languages(lang): assign_plugins(request, (placeholder,), template, fallback_language, is_fallback=True) fallback_plugins = placeholder._plugins_cache if fallback_plugins: fallbacks[placeholder.pk] += fallback_plugins break # These placeholders have no fallback non_fallback_phs = [ph for ph in placeholders if ph.pk not in fallbacks] # If no plugin is present in non fallback placeholders, create default plugins if enabled) if not plugins: plugins = create_default_plugins(request, non_fallback_phs, template, lang) plugins = downcast_plugins(plugins, non_fallback_phs, request=request) # split the plugins up by placeholder # Plugins should still be sorted by placeholder plugin_groups = dict((key, list(plugins)) for key, plugins in groupby(plugins, attrgetter('placeholder_id'))) all_plugins_groups = plugin_groups.copy() for group in plugin_groups: plugin_groups[group] = build_plugin_tree(plugin_groups[group]) groups = fallbacks.copy() groups.update(plugin_groups) for placeholder in placeholders: # This is all the plugins. setattr(placeholder, '_all_plugins_cache', all_plugins_groups.get(placeholder.pk, [])) # This one is only the root plugins. setattr(placeholder, '_plugins_cache', groups.get(placeholder.pk, []))
def get_current_page(path, lang, queryset, home_slug=None, home_tree_id=None): """Helper for getting current page from path depending on language returns: (Page, None) or (None, path_to_alternative language) """ try: if settings.CMS_FLAT_URLS: title_q = Q(title_set__slug=path) return queryset.filter(title_q & Q( title_set__language=lang)).distinct().select_related()[0], None else: if home_slug: #queryset = queryset.exclude(Q(title_set__path=home_slug)&Q(tree_id=home_tree_id)) home_slug += "/" title_q = Q(title_set__path=path) | ( Q(title_set__path=home_slug + path) & Q(tree_id=home_tree_id)) else: title_q = Q(title_set__slug=path) if settings.CMS_DBGETTEXT and settings.CMS_DBGETTEXT_SLUGS: # ugly hack -- brute force search for reverse path translation: from django.utils.translation import ugettext from cms.models import Title for t in Title.objects.all(): tpath = '/'.join([ugettext(x) for x in t.path.split('/')]) if path == tpath: title_q = Q(title_set__path=t.path) break page = queryset.filter(title_q).distinct().select_related()[0] if page: langs = page.get_languages() if lang in langs or settings.CMS_DBGETTEXT: return page, None else: path = None for alt_lang in get_fallback_languages(lang): if alt_lang in langs: path = '/%s%s' % (alt_lang, page.get_absolute_url( language=lang, fallback=True)) return None, path return None, path except IndexError: return None, None
def known_translation_getter(self, field, default=None, language_code=None, any_language=False): """ This is meant to act like HVAD/Parler's safe_translation_getter() but respects the fallback preferences as defined in `settings.CMS_LANGUAGES` and returns both the translated field value and the language it represents as a tuple: (value, language). If no suitable language is found, then it returns (default, None) """ # NOTE: We're using the CMS fallbacks here, rather than the Parler # fallbacks, the developer should ensure that their project's Parler # settings match the CMS settings. try: object_languages = self.get_available_languages() assert hasattr(object_languages, '__iter__') except [KeyError, AssertionError]: raise ImproperlyConfigured( "TranslationHelperMixin must be used with a model defining" "get_available_languages() that returns a list of available" "language codes. E.g., django-parler's TranslatableModel.") language_code = (language_code or get_current_language() or get_default_language()) site_id = getattr(settings, 'SITE_ID', None) languages = [language_code] + get_fallback_languages(language_code, site_id=site_id) # Grab the first language that is common to our list of fallbacks and # the list of available languages for this object. if languages and object_languages: language_code = next( (lang for lang in languages if lang in object_languages), None) if language_code: value = self.safe_translation_getter( field, default=default, language_code=language_code) return (value, language_code) # No suitable translation exists return (default, None)
def get_direct_related_page_extensions( self, extension_model, plugin_model, language=None ): """ Return the page extensions linked to this page via a plugin in a placeholder, ranked by their `path` to respect the order in the page tree. """ current_language = language or translation.get_language() site = get_current_site() languages = [current_language] + i18n.get_fallback_languages( current_language, site_id=site.pk ) existing_languages = ( plugin_model.objects.filter( cmsplugin_ptr__placeholder__page=self.extended_object ) .values_list("cmsplugin_ptr__language", flat=True) .distinct() ) relevant_language = next( filter(lambda l: l in existing_languages, languages), current_language ) related_name = plugin_model.page.field.related_query_name() selector = f"extended_object__{related_name:s}__cmsplugin_ptr" # pylint: disable=no-member filter_dict = { f"{selector:s}__language": relevant_language, f"{selector:s}__placeholder__page": self.extended_object, } # For a public course, we must filter out page extensions that are not published # in any language if self.extended_object.publisher_is_draft is False: filter_dict["extended_object__title_set__published"] = True return ( extension_model.objects.filter(**filter_dict) .select_related("extended_object") .order_by("extended_object__node__path") .distinct() )
def known_translation_getter(self, field, default=None, language_code=None, any_language=False): """ This is meant to act like HVAD/Parler's safe_translation_getter() but respects the fallback preferences as defined in `settings.CMS_LANGUAGES` and returns both the translated field value and the language it represents as a tuple: (value, language). If no suitable language is found, then it returns (default, None) """ # NOTE: We're using the CMS fallbacks here, rather than the Parler # fallbacks, the developer should ensure that their project's Parler # settings match the CMS settings. try: object_languages = self.get_available_languages() assert hasattr(object_languages, '__iter__') except [KeyError, AssertionError]: raise ImproperlyConfigured( "TranslationHelperMixin must be used with a model defining" "get_available_languages() that returns a list of available" "language codes. E.g., django-parler's TranslatableModel.") language_code = ( language_code or get_current_language() or get_default_language()) site_id = getattr(settings, 'SITE_ID', None) languages = [language_code] + get_fallback_languages( language_code, site_id=site_id) # Grab the first language that is common to our list of fallbacks and # the list of available languages for this object. if languages and object_languages: language_code = next( (lang for lang in languages if lang in object_languages), None) if language_code: value = self.safe_translation_getter(field, default=default, language_code=language_code) return (value, language_code) # No suitable translation exists return (default, None)
def get_page_path(self, lang): page = getattr(self.request, 'current_page', None) if not page: return '/%s/' % lang if settings.USE_I18N else '/' page_languages = page.get_published_languages() if lang in page_languages: return page.get_absolute_url(lang, fallback=False) site = get_current_site() if is_valid_site_language(lang, site_id=site.pk): _valid_language = True _hide_untranslated = hide_untranslated(lang, site.pk) else: _valid_language = False _hide_untranslated = False if _hide_untranslated and settings.USE_I18N: return '/%s/' % lang default_language = get_default_language_for_site(site.pk) if not _valid_language and default_language in page_languages: # The request language is not configured for the current site. # Fallback to the default language configured for the current site. return page.get_absolute_url(default_language, fallback=False) if _valid_language: fallbacks = get_fallback_languages(lang, site_id=site.pk) or [] fallbacks = [ _lang for _lang in fallbacks if _lang in page_languages ] else: fallbacks = [] if fallbacks: return page.get_absolute_url(fallbacks[0], fallback=False) return '/%s/' % lang if settings.USE_I18N else '/'
def get_plugin_language_fallback_clause(language, is_draft): """ Return a language fallback clause to apply in more complex queries where we select plugins and need to apply language fallbacks. """ site = get_current_site() languages = [language] + i18n.get_fallback_languages(language, site_id=site.pk) languages = list(dict.fromkeys(languages)) for item in range(len(languages)): for previous_item, previous_language in enumerate(languages[:item + 1]): qop_dict = { "extended_object__placeholders__cmsplugin__language": previous_language } if previous_item == item: if not is_draft: qop_dict.update({ "extended_object__title_set__language": previous_language, "extended_object__title_set__published": True, }) qop = models.Q(**qop_dict) else: qop = ~models.Q(**qop_dict) if previous_item == 0: subclause = qop else: subclause &= qop if item == 0: language_clause = subclause else: language_clause |= subclause return language_clause
def get_title(self, page, language, language_fallback=False): """ Gets the latest content for a particular page and language. Falls back to another language if wanted. """ try: title = self.get(language=language, page=page) return title except self.model.DoesNotExist: if language_fallback: try: titles = self.filter(page=page) fallbacks = get_fallback_languages(language) for l in fallbacks: for title in titles: if l == title.language: return title return None except self.model.DoesNotExist: pass return None
def get_current_page(path, lang, queryset, home_slug=None, home_tree_id=None): """Helper for getting current page from path depending on language returns: (Page, None) or (None, path_to_alternative language) """ try: if settings.CMS_FLAT_URLS: title_q = Q(title_set__slug=path) return queryset.filter(title_q & Q(title_set__language=lang)).distinct().select_related()[0], None else: if home_slug: queryset = queryset.exclude(Q(title_set__path=home_slug)&Q(tree_id=home_tree_id)) home_slug += "/" title_q = Q(title_set__path=path)|(Q(title_set__path=home_slug + path)&Q(tree_id=home_tree_id)) else: title_q = Q(title_set__slug=path) if settings.CMS_DBGETTEXT and settings.CMS_DBGETTEXT_SLUGS: # ugly hack -- brute force search for reverse path translation: from django.utils.translation import ugettext from cms.models import Title for t in Title.objects.all(): tpath = '/'.join([ugettext(x) for x in t.path.split('/')]) if path == tpath: title_q = Q(title_set__path=t.path) break page = queryset.filter(title_q).distinct().select_related()[0] if page: langs = page.get_languages() if lang in langs or settings.CMS_DBGETTEXT: return page, None else: path = None for alt_lang in get_fallback_languages(lang): if alt_lang in langs: path = '/%s%s' % (alt_lang, page.get_absolute_url(language=lang, fallback=True)) return None, path return None, path except IndexError: return None, None
def assign_plugins(request, placeholders, template, lang=None, is_fallback=False): """ Fetch all plugins for the given ``placeholders`` and cast them down to the concrete instances in one query per type. """ if not placeholders: return placeholders = tuple(placeholders) lang = lang or get_language_from_request(request) qs = get_cmsplugin_queryset(request) qs = qs.filter(placeholder__in=placeholders, language=lang) plugins = list(qs.order_by('placeholder', 'path')) # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if (not is_fallback and not (hasattr(request, 'toolbar') and request.toolbar.edit_mode)): disjoint_placeholders = (ph for ph in placeholders if all(ph.pk != p.placeholder_id for p in plugins)) for placeholder in disjoint_placeholders: if get_placeholder_conf("language_fallback", placeholder.slot, template, True): for fallback_language in get_fallback_languages(lang): assign_plugins(request, (placeholder,), template, fallback_language, is_fallback=True) fallback_plugins = placeholder._plugins_cache if fallback_plugins: plugins += fallback_plugins break # If no plugin is present, create default plugins if enabled) if not plugins: plugins = create_default_plugins(request, placeholders, template, lang) plugins = downcast_plugins(plugins, placeholders) # split the plugins up by placeholder # Plugins should still be sorted by placeholder groups = dict((ph_id, build_plugin_tree(ph_plugins)) for ph_id, ph_plugins in groupby(plugins, attrgetter('placeholder_id'))) for placeholder in placeholders: setattr(placeholder, '_plugins_cache', groups.get(placeholder.pk, []))
def get_title(self, page, language, language_fallback=False): """ Gets the latest content for a particular page and language. Falls back to another language if wanted. """ try: title = self.get(language=language, page=page) return title except self.model.DoesNotExist: if language_fallback: try: titles = self.filter(page=page) fallbacks = get_fallback_languages(language) for lang in fallbacks: for title in titles: if lang == title.language: return title return None except self.model.DoesNotExist: pass else: raise return None
def get_teaser(self, page, language, language_fallback=False): """ Gets the latest content for a particular page and language. Falls back to another language if wanted. """ try: teaser = self.get(language=language, page=page) return teaser except self.model.DoesNotExist: if language_fallback: try: teasers = self.filter(page=page) fallbacks = get_fallback_languages(language) for lang in fallbacks: for teaser in teasers: if lang == teaser.language: return teaser return None except self.model.DoesNotExist: pass else: raise return None
def _get_title_cache(self, language, fallback, version_id, force_reload): if not language: language = get_language() load = False if not hasattr(self, "title_cache") or force_reload: load = True self.title_cache = {} elif not language in self.title_cache: if fallback: fallback_langs = i18n.get_fallback_languages(language) for lang in fallback_langs: if lang in self.title_cache: return lang load = True if load: from cms.models.titlemodels import Title if version_id: from reversion.models import Version version = get_object_or_404(Version, pk=version_id) revs = [ related_version.object_version for related_version in version.revision.version_set.all() ] for rev in revs: obj = rev.object if obj.__class__ == Title: self.title_cache[obj.language] = obj else: title = Title.objects.get_title(self, language, language_fallback=fallback) if title: self.title_cache[title.language] = title language = title.language return language
def get_current_page(path, lang, queryset, home_slug, home_tree_id): """Helper for getting current page from path depending on language returns: (Page, None) or (None, path_to_alternative language) """ try: if settings.CMS_FLAT_URLS: title_q = Q(title_set__slug=path) return queryset.filter(title_q & Q( title_set__language=lang)).distinct().select_related()[0], None else: if home_slug: queryset = queryset.exclude( Q(title_set__path=home_slug) & Q(tree_id=home_tree_id)) home_slug += "/" title_q = Q(title_set__path=path) | ( Q(title_set__path=home_slug + path) & Q(tree_id=home_tree_id)) else: title_q = Q(title_set__slug=path) page = queryset.filter(title_q).distinct().select_related()[0] if page: langs = page.get_languages() if lang in langs: return page, None else: path = None for alt_lang in get_fallback_languages(lang): if alt_lang in langs: path = '/%s%s' % (alt_lang, page.get_absolute_url( language=lang, fallback=True)) return None, path return None, path except IndexError: return None, None
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ # get the right model context = RequestContext(request) # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = get_language_from_request(request) # Check that the current page is available in the desired (current) language available_languages = page.get_languages() # We resolve an alternate language for the page if it's not available. # Since the "old" details view had an exception for the root page, it is # ported here. So no resolution if the slug is ''. if (current_language not in available_languages) and (slug != ''): if settings.CMS_LANGUAGE_FALLBACK: # If we didn't find the required page in the requested (current) # language, let's try to find a suitable fallback in the list of # fallback languages (CMS_LANGUAGE_CONF) for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: alt_url = page.get_absolute_url(language=alt_lang, fallback=True) path = '/%s%s' % (alt_lang, alt_url) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). return HttpResponseRedirect(path) # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) if app_urls: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if settings.i18n_installed and redirect_url[0] == "/": redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # add language prefix to url return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): if settings.i18n_installed: path = urlquote("/%s%s" % (request.LANGUAGE_CODE, request.get_full_path())) else: path = urlquote(request.get_full_path()) tup = django_settings.LOGIN_URL , "next", path return HttpResponseRedirect('%s?%s=%s' % tup) if page.login_required and not page.has_view_permission(request): return HttpResponseForbidden("You don't have the rights to access this resource") template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) return render_to_response(template_name, context)
def get_public_page_with_fallbacks(page, request): """ the plugin should show the published page whenever it exists or the draft page otherwise. On a public content, the draft page should not be shown at all but this is left to the caller. This is inspired by what DjangoCMS does in its main view: https://github.com/django-cms/django-cms/blob/3.8.0/cms/views.py#L37 """ page = page.get_public_object() request_language = translation.get_language_from_request(request, check_path=True) if not page: return None # Check permissions site = get_current_site() if not page_permissions.user_can_view_page(request.user, page, site): return None if request.user.is_staff: user_languages = i18n.get_language_list(site_id=site.pk) else: user_languages = i18n.get_public_languages(site_id=site.pk) # These languages are then filtered out by the user allowed languages available_languages = [ language for language in user_languages if language in list(page.get_published_languages()) ] if request_language not in user_languages: # Language is not allowed # Use the default site language default_language = i18n.get_default_language_for_site(site.pk) fallbacks = i18n.get_fallback_languages(default_language, site_id=site.pk) fallbacks = [default_language] + fallbacks else: fallbacks = i18n.get_fallback_languages(request_language, site_id=site.pk) # Only fallback to languages the user is allowed to see fallback_languages = [ language for language in fallbacks if language != request_language and language in available_languages ] if request_language not in available_languages: if not fallback_languages: # There is no page with the requested language # and there's no configured fallbacks return None if request_language in page.get_languages(): # The page was already published and later unpublished in the current # language. In this case we must not fallback to another language. return None return page
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ # get the right model context = RequestContext(request) # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = get_language_from_request(request) # Check that the current page is available in the desired (current) language available_languages = [] page_languages = list(page.get_languages()) if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() else: user_languages = get_public_languages() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) attrs = '' if 'edit' in request.GET: attrs = '?edit=1' elif 'preview' in request.GET: attrs = '?preview=1' if 'draft' in request.GET: attrs += '&draft=1' # Check that the language is in FRONTEND_LANGUAGES: if not current_language in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: with SettingsOverride(LANGUAGES=languages, LANGUAGE_CODE=languages[0][0]): #get supported language new_language = get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') return HttpResponseRedirect(pages_root + attrs) else: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language): with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). return HttpResponseRedirect(path + attrs) else: found = True if not found: # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! try: app_urls = page.get_application_urls(current_language, False) except Title.DoesNotExist: app_urls = [] if app_urls: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (is_language_prefix_patterns_used() and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if redirect_url not in own_urls: return HttpResponseRedirect(redirect_url + attrs) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) return TemplateResponse(request, template_name, context)
def get_nodes(self, request): page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) filters = { 'site': site, } if settings.CMS_HIDE_UNTRANSLATED: filters['title_set__language'] = lang pages = page_queryset.published().filter(**filters).order_by( "tree_id", "lft") ids = [] nodes = [] first = True home_cut = False home_children = [] home = None actual_pages = [] # cache view perms visible_pages = get_visible_pages(request, pages, site) for page in pages: # Pages are ordered by tree_id, therefore the first page is the root # of the page tree (a.k.a "home") if page.pk not in visible_pages: # Don't include pages the user doesn't have access to continue if not home: home = page page.home_pk_cache = home.pk if first and page.pk != home.pk: home_cut = True if (page.parent_id == home.pk or page.parent_id in home_children) and home_cut: home_children.append(page.pk) if (page.pk == home.pk and home.in_navigation) or page.pk != home.pk: first = False ids.append(page.id) actual_pages.append(page) titles = list( get_title_queryset(request).filter(page__in=ids, language=lang)) for page in actual_pages: # add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) if ids: # get fallback languages fallbacks = get_fallback_languages(lang) for l in fallbacks: titles = list( get_title_queryset(request).filter(page__in=ids, language=l)) for title in titles: for page in actual_pages: # add the title and slugs and some meta data if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) break if not ids: break return nodes
def get_nodes(self, request): from cms.models import Title site = self.renderer.site lang = self.renderer.request_language pages = get_page_queryset( site, draft=self.renderer.draft_mode_active, published=not self.renderer.draft_mode_active, ) if is_valid_site_language(lang, site_id=site.pk): _valid_language = True _hide_untranslated = hide_untranslated(lang, site.pk) else: _valid_language = False _hide_untranslated = False if _valid_language: # The request language has been explicitly configured # for the current site. if _hide_untranslated: fallbacks = [] else: fallbacks = get_fallback_languages(lang, site_id=site.pk) languages = [lang ] + [_lang for _lang in fallbacks if _lang != lang] else: # The request language is not configured for the current site. # Fallback to all configured public languages for the current site. languages = get_public_languages(site.pk) fallbacks = languages pages = (pages.filter(title_set__language__in=languages). select_related('node').order_by('node__path').distinct()) if not self.renderer.draft_mode_active: # we're dealing with public pages. # prefetch the draft versions. pages = pages.select_related('publisher_public__node') pages = get_visible_nodes(request, pages, site) if not pages: return [] try: homepage = [page for page in pages if page.is_home][0] except IndexError: homepage = None titles = Title.objects.filter( language__in=languages, publisher_is_draft=self.renderer.draft_mode_active, ) lookup = Prefetch( 'title_set', to_attr='filtered_translations', queryset=titles, ) prefetch_related_objects(pages, lookup) # Build the blank title instances only once blank_title_cache = { language: EmptyTitle(language=language) for language in languages } if lang not in blank_title_cache: blank_title_cache[lang] = EmptyTitle(language=lang) # Maps a node id to its page id node_id_to_page = {} def _page_to_node(page): # EmptyTitle is used to prevent the cms from trying # to find a translation in the database page.title_cache = blank_title_cache.copy() for trans in page.filtered_translations: page.title_cache[trans.language] = trans menu_node = get_menu_node_for_page( self.renderer, page, language=lang, fallbacks=fallbacks, ) return menu_node menu_nodes = [] for page in pages: node = page.node parent_id = node_id_to_page.get(node.parent_id) if node.parent_id and not parent_id: # If the parent page is not available (unpublished, etc..) # don't bother creating menu nodes for its descendants. continue menu_node = _page_to_node(page) cut_homepage = homepage and not homepage.in_navigation if cut_homepage and parent_id == homepage.pk: # When the homepage is hidden from navigation, # we need to cut all its direct children from it. menu_node.parent_id = None else: menu_node.parent_id = parent_id node_id_to_page[node.pk] = page.pk menu_nodes.append(menu_node) return menu_nodes
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ response_timestamp = now() if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or (not request.toolbar.edit_mode_active and not request.toolbar.show_toolbar and not request.user.is_authenticated())): cache_content = get_page_cache(request) if cache_content is not None: content, headers, expires_datetime = cache_content response = HttpResponse(content) response._headers = headers # Recalculate the max-age header for this cached response max_age = int((expires_datetime - response_timestamp).total_seconds() + 0.5) patch_cache_control(response, max_age=max_age) return response # Get a Page model object from the request site = get_current_site() page = get_page_from_request(request, use_path=slug) toolbar = get_toolbar_from_request(request) tree_nodes = TreeNode.objects.get_for_site(site) if not page and not slug and not tree_nodes.exists(): # render the welcome page if the requested path is root "/" # and there's no pages return _render_welcome_page(request) if not page: # raise 404 _handle_no_page(request) request.current_page = page if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list(site_id=site.pk) else: user_languages = get_public_languages(site_id=site.pk) request_language = get_language_from_request(request, check_path=True) if not page.is_home and request_language not in user_languages: # The homepage is treated differently because # when a request goes to the root of the site (/) # without a language, Django will redirect to the user's # browser language which might not be a valid cms language, # this means we need to correctly redirect that request. return _handle_no_page(request) # get_published_languages will return all languages in draft mode # and published only in live mode. # These languages are then filtered out by the user allowed languages available_languages = [ language for language in user_languages if language in list(page.get_published_languages()) ] own_urls = [ request.build_absolute_uri(request.path), '/%s' % request.path, request.path, ] try: redirect_on_fallback = get_redirect_on_fallback(request_language, site_id=site.pk) except LanguageError: redirect_on_fallback = False if request_language not in user_languages: # Language is not allowed # Use the default site language default_language = get_default_language_for_site(site.pk) fallbacks = get_fallback_languages(default_language, site_id=site.pk) fallbacks = [default_language] + fallbacks else: fallbacks = get_fallback_languages(request_language, site_id=site.pk) # Only fallback to languages the user is allowed to see fallback_languages = [ language for language in fallbacks if language != request_language and language in available_languages ] language_is_unavailable = request_language not in available_languages if language_is_unavailable and not fallback_languages: # There is no page with the requested language # and there's no configured fallbacks return _handle_no_page(request) elif language_is_unavailable and (redirect_on_fallback or page.is_home): # There is no page with the requested language and # the user has explicitly requested to redirect on fallbacks, # so redirect to the first configured / available fallback language fallback = fallback_languages[0] redirect_url = page.get_absolute_url(fallback, fallback=False) else: page_path = page.get_absolute_url(request_language) page_slug = page.get_path(request_language) or page.get_slug( request_language) if slug and slug != page_slug and request.path[:len(page_path )] != page_path: # The current language does not match its slug. # Redirect to the current language. return HttpResponseRedirect(page_path) # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(request_language, fallback=False) or '' redirect_url = _clean_redirect_url(redirect_url, request_language) if redirect_url: if request.user.is_staff and toolbar.edit_mode_active: toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: # prevent redirect to self return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) structure_requested = get_cms_setting( 'CMS_TOOLBAR_URL__BUILD') in request.GET if user_can_change_page(request.user, page) and structure_requested: return render_object_structure(request, page) return render_page(request, page, current_language=request_language, slug=slug)
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ from django.core.cache import cache if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or (not request.toolbar.edit_mode and not request.toolbar.show_toolbar and not request.user.is_authenticated())): cache_content = cache.get(_get_cache_key(request), version=_get_cache_version()) if not cache_content is None: content, headers = cache_content response = HttpResponse(content) response._headers = headers return response # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = request.REQUEST.get('language', None) if current_language: current_language = get_language_code(current_language) if not current_language in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code( getattr(request, 'LANGUAGE_CODE', None)) if current_language: current_language = get_language_code(current_language) if not current_language in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(get_language()) # Check that the current page is available in the desired (current) language available_languages = [] page_languages = list(page.get_languages()) if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() else: user_languages = get_public_languages() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) # Check that the language is in FRONTEND_LANGUAGES: own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if not current_language in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: with SettingsOverride(LANGUAGES=languages, LANGUAGE_CODE=languages[0][0]): #get supported language new_language = get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') if hasattr( request, 'toolbar' ) and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = pages_root elif pages_root not in own_urls: return HttpResponseRedirect(pages_root) elif not hasattr(request, 'toolbar') or not request.toolbar.redirect_url: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language) or slug == "": with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). if hasattr( request, 'toolbar' ) and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = path elif path not in own_urls: return HttpResponseRedirect(path) else: found = True if not found and (not hasattr(request, 'toolbar') or not request.toolbar.redirect_url): # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) skip_app = False if not page.is_published(current_language) and hasattr( request, 'toolbar') and request.toolbar.edit_mode: skip_app = True if app_urls and not skip_app: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (is_language_prefix_patterns_used() and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self if hasattr(request, 'toolbar' ) and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context = RequestContext(request) context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) response = TemplateResponse(request, template_name, context) response.add_post_render_callback(_cache_page) # Add headers for X Frame Options - this really should be changed upon moving to class based views xframe_options = page.get_xframe_options() if xframe_options == Page.X_FRAME_OPTIONS_INHERIT: # This is when we defer to django's own clickjacking handling return response # We want to prevent django setting this in their middlewear response.xframe_options_exempt = True if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: # Do nothing, allowed is no header. return response elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: response['X-Frame-Options'] = 'SAMEORIGIN' elif xframe_options == Page.X_FRAME_OPTIONS_DENY: response['X-Frame-Options'] = 'DENY' return response
def article(request, slug): """ The main view of the Django-CMS Articles! Takes a request and a slug, renders the article. """ # Get current CMS Page as article tree tree = request.current_page # Check whether it really is a tree. # It could also be one of its sub-pages. if tree.application_urls != 'CMSArticlesApp': # In such case show regular CMS Page return page(request, slug) # Get an Article object from the request draft = use_draft(request) and request.user.has_perm( 'cms_articles.change_article') preview = 'preview' in request.GET and request.user.has_perm( 'cms_articles.change_article') site = tree.node.site article = get_article_from_slug(tree, slug, preview, draft) if not article: # raise 404 _handle_no_page(request) request.current_article = article if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list(site_id=site.pk) else: user_languages = get_public_languages(site_id=site.pk) request_language = get_language_from_request(request, check_path=True) # get_published_languages will return all languages in draft mode # and published only in live mode. # These languages are then filtered out by the user allowed languages available_languages = [ language for language in user_languages if language in list(article.get_published_languages()) ] own_urls = [ request.build_absolute_uri(request.path), '/%s' % request.path, request.path, ] try: redirect_on_fallback = get_redirect_on_fallback(request_language, site_id=site.pk) except LanguageError: redirect_on_fallback = False if request_language not in user_languages: # Language is not allowed # Use the default site language default_language = get_default_language_for_site(site.pk) fallbacks = get_fallback_languages(default_language, site_id=site.pk) fallbacks = [default_language] + fallbacks else: fallbacks = get_fallback_languages(request_language, site_id=site.pk) # Only fallback to languages the user is allowed to see fallback_languages = [ language for language in fallbacks if language != request_language and language in available_languages ] language_is_unavailable = request_language not in available_languages if language_is_unavailable and not fallback_languages: # There is no page with the requested language # and there's no configured fallbacks return _handle_no_page(request) elif language_is_unavailable and redirect_on_fallback: # There is no page with the requested language and # the user has explicitly requested to redirect on fallbacks, # so redirect to the first configured / available fallback language fallback = fallback_languages[0] redirect_url = article.get_absolute_url(fallback, fallback=False) else: redirect_url = False if redirect_url: if request.user.is_staff and hasattr( request, 'toolbar') and request.toolbar.edit_mode_active: request.toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: # prevent redirect to self return HttpResponseRedirect(redirect_url) # permission checks if article.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.obj = article structure_requested = get_cms_setting( 'CMS_TOOLBAR_URL__BUILD') in request.GET if article.has_change_permission(request) and structure_requested: return render_object_structure(request, article) return render_article(request, article, current_language=request_language, slug=slug)
def test_get_fallback_languages(self): languages = i18n.get_fallback_languages('en', 1) self.assertEqual(languages, ['de', 'fr'])
def show_menu(context, from_level=0, to_level=100, extra_inactive=0, extra_active=100, template="cms/menu.html", next_page=None, root_id=None): """ render a nested list of all children of the pages from_level: is the start level to_level: is the max level rendered render_children: if set to True will render all not direct ascendants too """ try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return {'template': 'cms/empty.html'} page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) current_page = request.current_page if current_page == "dummy": context.update({'children':[], 'template':template, 'from_level':from_level, 'to_level':to_level, 'extra_inactive':extra_inactive, 'extra_active':extra_active}) return context if hasattr(current_page, "home_pk_cache"): home_pk = current_page.home_pk_cache else: try: home_pk = page_queryset.get_home(site).pk except NoHomeFound: home_pk = 0 if not next_page: #new menu... get all the data so we can save a lot of queries children = [] ancestors = [] if current_page: alist = current_page.get_ancestors().values_list('id', 'soft_root') else:# maybe the active node is in an extender? alist = [] extenders = page_queryset.published().filter(in_navigation=True, site=site, level__lte=to_level) extenders = extenders.exclude(navigation_extenders__isnull=True).exclude( navigation_extenders__exact="") for ext in extenders: ext.childrens = [] ext.ancestors_ascending = [] get_extended_navigation_nodes(request, 100, [ext], ext.level, 100, 100, False, ext.navigation_extenders) if hasattr(ext, "ancestor"): alist = list(ext.get_ancestors().values_list('id', 'soft_root')) alist = [(ext.pk, ext.soft_root)] + alist break filters = {'in_navigation' : True, 'site' : site, 'level__lte' : to_level} #check the ancestors for softroots soft_root_pk = None for p in alist: ancestors.append(p[0]) if p[1]: soft_root_pk = p[0] #modify filters if we don't start from the root root_page = None if root_id: try: root_page = page_queryset.get(reverse_id=root_id, site=site) except: send_missing_mail(root_id, request) else: if current_page and current_page.soft_root: root_page = current_page soft_root_pk = current_page.pk elif soft_root_pk: root_page = page_queryset.get(pk=soft_root_pk) if root_page: if isinstance(root_page, int): root_page = page_queryset.get(pk=root_page) if isinstance(root_page, Page): root_page = page_queryset.get(pk=root_page.id) elif isinstance(root_page, unicode): root_page = page_queryset.get(reverse_id=root_page, site=site) filters['tree_id'] = root_page.tree_id filters['lft__gt'] = root_page.lft filters['rght__lt'] = root_page.rght filters['level__lte'] = root_page.level + to_level db_from_level = root_page.level + from_level else: db_from_level = from_level if settings.CMS_HIDE_UNTRANSLATED: filters['title_set__language'] = lang if not request.user.is_authenticated(): filters['menu_login_required'] = False pages = page_queryset.published().filter(**filters).order_by('tree_id', 'parent', 'lft') pages = list(pages) if root_page: pages = [root_page] + pages all_pages = pages[:] root_level = getattr(root_page, 'level', None) ids = [] for page in pages:# build the tree if page.level >= db_from_level: ids.append(page.pk) if page.level == 0 or page.level == root_level: if page.parent_id: page.get_cached_ancestors() else: page.ancestors_ascending = [] page.home_pk_cache = home_pk page.menu_level = 0 - from_level page.childrens = [] children.append(page) if page.pk == soft_root_pk: page.soft_root = False #ugly hack for the recursive function if current_page: pk = current_page.pk else: pk = -1 find_children(page, pages, extra_inactive, extra_active, ancestors, pk, request=request, to_levels=to_level) if page.pk == soft_root_pk: page.soft_root = True if db_from_level > 0: children = cut_levels(children, db_from_level) titles = list(get_title_queryset(request).filter(page__in=ids, language=lang)) for page in all_pages:# add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title ids.remove(page.pk) if page.pk in ancestors: page.ancestor = True if current_page and page.parent_id == current_page.parent_id and not page.pk == current_page.pk: page.sibling = True if ids: fallbacks = get_fallback_languages(lang) for l in fallbacks: titles = list(get_title_queryset(request).filter(page__in=ids, language=l)) for page in all_pages:# add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title ids.remove(page.pk) if not ids: break children = navigation.handle_navigation_manipulators(children, request) else: children = next_page.childrens context.update({'children':children, 'template':template, 'from_level':from_level, 'to_level':to_level, 'extra_inactive':extra_inactive, 'extra_active':extra_active}) return context
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ from django.core.cache import cache if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or ( not request.toolbar.edit_mode and not request.toolbar.show_toolbar and not request.user.is_authenticated() ) ): cache_content = cache.get( _get_cache_key(request), version=_get_cache_version() ) if not cache_content is None: content, headers = cache_content response = HttpResponse(content) response._headers = headers return response # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = request.REQUEST.get('language', None) if current_language: current_language = get_language_code(current_language) if not current_language in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(getattr(request, 'LANGUAGE_CODE', None)) if current_language: current_language = get_language_code(current_language) if not current_language in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(get_language()) # Check that the current page is available in the desired (current) language available_languages = [] page_languages = list(page.get_languages()) if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() else: user_languages = get_public_languages() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) # Check that the language is in FRONTEND_LANGUAGES: own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if not current_language in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: with SettingsOverride(LANGUAGES=languages, LANGUAGE_CODE=languages[0][0]): #get supported language new_language = get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') if hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = pages_root elif pages_root not in own_urls: return HttpResponseRedirect(pages_root) elif not hasattr(request, 'toolbar') or not request.toolbar.redirect_url: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language) or slug == "": with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). if hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = path elif path not in own_urls: return HttpResponseRedirect(path) else: found = True if not found and (not hasattr(request, 'toolbar') or not request.toolbar.redirect_url): # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) skip_app = False if not page.is_published(current_language) and hasattr(request, 'toolbar') and request.toolbar.edit_mode: skip_app = True if app_urls and not skip_app: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (is_language_prefix_patterns_used() and redirect_url[0] == "/" and not redirect_url.startswith( '/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self if hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context = RequestContext(request) context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) response = TemplateResponse(request, template_name, context) response.add_post_render_callback(_cache_page) # Add headers for X Frame Options - this really should be changed upon moving to class based views xframe_options = page.get_xframe_options() if xframe_options == Page.X_FRAME_OPTIONS_INHERIT: # This is when we defer to django's own clickjacking handling return response # We want to prevent django setting this in their middlewear response.xframe_options_exempt = True if xframe_options == Page.X_FRAME_OPTIONS_ALLOW: # Do nothing, allowed is no header. return response elif xframe_options == Page.X_FRAME_OPTIONS_SAMEORIGIN: response['X-Frame-Options'] = 'SAMEORIGIN' elif xframe_options == Page.X_FRAME_OPTIONS_DENY: response['X-Frame-Options'] = 'DENY' return response
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ # get the right model context = RequestContext(request) # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = get_language_from_request(request) # Check that the current page is available in the desired (current) language available_languages = page.get_languages() # We resolve an alternate language for the page if it's not available. # Since the "old" details view had an exception for the root page, it is # ported here. So no resolution if the slug is ''. if (current_language not in available_languages): if settings.CMS_LANGUAGE_FALLBACK: # If we didn't find the required page in the requested (current) # language, let's try to find a suitable fallback in the list of # fallback languages (CMS_LANGUAGE_CONF) for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: alt_url = page.get_absolute_url(language=alt_lang, fallback=True) path = '/%s%s' % (alt_lang, alt_url) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). return HttpResponseRedirect(path) # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) if app_urls: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (settings.i18n_installed and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # add language prefix to url return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): if settings.i18n_installed: path = urlquote("/%s%s" % (request.LANGUAGE_CODE, request.get_full_path())) else: path = urlquote(request.get_full_path()) tup = settings.LOGIN_URL, "next", path return HttpResponseRedirect('%s?%s=%s' % tup) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) return render_to_response(template_name, context)
def has_fallback_language(language): try: language_list = get_fallback_languages(language) return len(language_list) > 0 except: return False
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ from cms.apphook_pool import apphook_pool from cms.appresolver import get_app_urls from cms.utils import get_template_from_request, get_language_from_request from cms.utils.i18n import get_fallback_languages from cms.utils.django_load import load_object from cms.utils.page_resolver import get_page_from_request from cms.views import _handle_no_page from django.conf import settings from django.conf.urls import patterns from django.core.urlresolvers import resolve, Resolver404 from django.http import Http404, HttpResponseRedirect from django.shortcuts import render_to_response from django.template.context import RequestContext from django.utils.http import urlquote # get the right model context = RequestContext(request) # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = get_language_from_request(request) # Check that the current page is available in the desired (current) language available_languages = page.get_languages() # We resolve an alternate language for the page if it's not available. # Since the "old" details view had an exception for the root page, it is # ported here. So no resolution if the slug is ''. if (current_language not in available_languages): if settings.CMS_LANGUAGE_FALLBACK: # If we didn't find the required page in the requested (current) # language, let's try to find a suitable fallback in the list of # fallback languages (CMS_LANGUAGE_CONF) for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: alt_url = page.get_absolute_url(language=alt_lang, fallback=True) path = '/%s%s' % (alt_lang, alt_url) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). return HttpResponseRedirect(path) # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) if app_urls: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass if page.view_path: view = load_object(page.view_path) args, kwargs = view.extract_args_kwargs(slug) return view(request, *args, **kwargs) # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (settings.i18n_installed and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s%s' % (current_language, request.path), request.path, ] if redirect_url not in own_urls: return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): if settings.i18n_installed: path = urlquote("/%s%s" % (request.LANGUAGE_CODE, request.get_full_path())) else: path = urlquote(request.get_full_path()) tup = settings.LOGIN_URL , "next", path return HttpResponseRedirect('%s?%s=%s' % tup) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) return render_to_response(template_name, context)
def get_nodes(self, request): page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) filters = { 'site':site, } if settings.CMS_HIDE_UNTRANSLATED: filters['title_set__language'] = lang pages = page_queryset.published().filter(**filters).order_by("tree_id", "lft") ids = [] nodes = [] first = True home_cut = False home_children = [] home = None actual_pages = [] # cache view perms visible_pages = get_visible_pages(request, pages, site) for page in pages: # Pages are ordered by tree_id, therefore the first page is the root # of the page tree (a.k.a "home") if page.pk not in visible_pages: # Don't include pages the user doesn't have access to continue if not home: home = page page.home_pk_cache = home.pk if first and page.pk != home.pk: home_cut = True if (page.parent_id == home.pk or page.parent_id in home_children) and home_cut: home_children.append(page.pk) if (page.pk == home.pk and home.in_navigation) or page.pk != home.pk: first = False ids.append(page.id) actual_pages.append(page) titles = list(get_title_queryset(request).filter(page__in=ids, language=lang)) for page in actual_pages: # add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) if ids: # get fallback languages fallbacks = get_fallback_languages(lang) for lang in fallbacks: titles = list(get_title_queryset(request).filter(page__in=ids, language=lang)) for title in titles: for page in actual_pages: # add the title and slugs and some meta data if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title nodes.append(page_to_node(page, home, home_cut)) ids.remove(page.pk) break if not ids: break return nodes
def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder", lang=None): """ 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'] page = placeholder.page if placeholder else None if page: template = page.template else: template = None # It's kind of duplicate of the similar call in `get_plugins`, but it's required # to have a valid language in this function for `get_fallback_languages` to work if not lang: lang = get_language_from_request(request) plugins = [ plugin for plugin in get_plugins(request, placeholder, lang=lang) ] # If no plugin is present in the current placeholder we loop in the fallback languages # and get the first available set of plugins if (len(plugins) == 0 and placeholder and get_placeholder_conf( "language_fallback", placeholder.slot, template, False)): fallbacks = get_fallback_languages(lang) for fallback_language in fallbacks: plugins = [ plugin for plugin in get_plugins(request, placeholder, fallback_language) ] if plugins: break # 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 content = [] # 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 content.extend(render_plugins(plugins, context, placeholder, processors)) toolbar_content = '' draggable_content = '' if edit: toolbar_content = mark_safe( render_placeholder_toolbar(placeholder, context, '', name_fallback=name_fallback)) draggable_content = mark_safe(render_dragables(plugins, slot, request)) content = mark_safe("".join(content)) result = render_to_string( "cms/toolbar/placeholder.html", { 'plugins': content, "bar": toolbar_content, "draggables": draggable_content, 'edit': edit }) context.pop() return result
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ # get the right model context = RequestContext(request) # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = get_language_from_request(request) # Check that the current page is available in the desired (current) language available_languages = [] page_languages = page.get_languages() user_languages = get_public_languages() if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) attrs = '' if 'edit' in request.GET: attrs = '?edit=1' elif 'preview' in request.GET: attrs = '?preview=1' if 'draft' in request.GET: attrs += '&draft=1' # Check that the language is in FRONTEND_LANGUAGES: if not current_language in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: with SettingsOverride(LANGUAGES=languages, LANGUAGE_CODE=languages[0][0]): #get supported language new_language = translation.get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') return HttpResponseRedirect(pages_root + attrs) else: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language): with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). return HttpResponseRedirect(path + attrs) else: found = True if not found: # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! try: app_urls = page.get_application_urls(current_language, False) except Title.DoesNotExist: app_urls = [] if app_urls: app = apphook_pool.get_apphook(app_urls) pattern_list = [] for urlpatterns in get_app_urls(app.urls): pattern_list += urlpatterns urlpatterns = patterns('', *pattern_list) try: context.current_app = page.reverse_id if page.reverse_id else app.app_name view, args, kwargs = resolve('/', tuple(urlpatterns)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (settings.USE_I18N and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if redirect_url not in own_urls: return HttpResponseRedirect(redirect_url + attrs) # permission checks if page.login_required and not request.user.is_authenticated(): path = urlquote(request.get_full_path()) tup = settings.LOGIN_URL, "next", path return HttpResponseRedirect('%s?%s=%s' % tup) template_name = get_template_from_request(request, page, no_current_page=True) # fill the context context['lang'] = current_language context['current_page'] = page context['has_change_permissions'] = page.has_change_permission(request) context['has_view_permissions'] = page.has_view_permission(request) if not context['has_view_permissions']: return _handle_no_page(request, slug) return render_to_response(template_name, context_instance=context)
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ response_timestamp = now() if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or (not request.toolbar.edit_mode and not request.toolbar.show_toolbar and not request.user.is_authenticated())): cache_content = get_page_cache(request) if cache_content is not None: content, headers, expires_datetime = cache_content response = HttpResponse(content) response._headers = headers # Recalculate the max-age header for this cached response max_age = int((expires_datetime - response_timestamp).total_seconds() + 0.5) patch_cache_control(response, max_age=max_age) return response # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = request.GET.get('language', None) if not current_language: current_language = request.POST.get('language', None) if current_language: current_language = get_language_code(current_language) if current_language not in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code( getattr(request, 'LANGUAGE_CODE', None)) if current_language: current_language = get_language_code(current_language) if current_language not in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(get_language()) # Check that the current page is available in the desired (current) language available_languages = [] # this will return all languages in draft mode, and published only in live mode page_languages = list(page.get_published_languages()) if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() else: user_languages = get_public_languages() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) # Check that the language is in FRONTEND_LANGUAGES: own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if current_language not in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: # get supported language new_language = get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') if (hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode): request.toolbar.redirect_url = pages_root elif pages_root not in own_urls: return HttpResponseRedirect(pages_root) elif not hasattr(request, 'toolbar') or not request.toolbar.redirect_url: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language) or slug == "": with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). if (hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode): request.toolbar.redirect_url = path elif path not in own_urls: return HttpResponseRedirect(path) else: found = True if not found and (not hasattr(request, 'toolbar') or not request.toolbar.redirect_url): # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) else: page_path = page.get_absolute_url(language=current_language) page_slug = page.get_path(language=current_language) or page.get_slug( language=current_language) if slug and slug != page_slug and request.path[:len(page_path )] != page_path: # The current language does not match it's slug. # Redirect to the current language. if hasattr( request, 'toolbar' ) and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = page_path else: return HttpResponseRedirect(page_path) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) skip_app = False if (not page.is_published(current_language) and hasattr(request, 'toolbar') and request.toolbar.edit_mode): skip_app = True if app_urls and not skip_app: app = apphook_pool.get_apphook(app_urls) pattern_list = [] if app: for urlpatterns in get_app_urls( app.get_urls(page, current_language)): pattern_list += urlpatterns try: view, args, kwargs = resolve('/', tuple(pattern_list)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (is_language_prefix_patterns_used() and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self if hasattr(request, 'toolbar' ) and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) response = render_page(request, page, current_language=current_language, slug=slug) return response
def test_get_fallback_languages(self): languages = i18n.get_fallback_languages("en", 1) self.assertEqual(languages, ["de", "fr"])
def details(request, slug): """ The main view of the Django-CMS! Takes a request and a slug, renders the page. """ response_timestamp = now() if get_cms_setting("PAGE_CACHE") and ( not hasattr(request, 'toolbar') or ( not request.toolbar.edit_mode and not request.toolbar.show_toolbar and not request.user.is_authenticated() ) ): cache_content = get_page_cache(request) if cache_content is not None: content, headers, expires_datetime = cache_content response = HttpResponse(content) response._headers = headers # Recalculate the max-age header for this cached response max_age = int( (expires_datetime - response_timestamp).total_seconds() + 0.5) patch_cache_control(response, max_age=max_age) return response # Get a Page model object from the request page = get_page_from_request(request, use_path=slug) if not page: return _handle_no_page(request, slug) current_language = request.GET.get('language', None) if not current_language: current_language = request.POST.get('language', None) if current_language: current_language = get_language_code(current_language) if current_language not in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(getattr(request, 'LANGUAGE_CODE', None)) if current_language: current_language = get_language_code(current_language) if current_language not in get_language_list(page.site_id): current_language = None if current_language is None: current_language = get_language_code(get_language()) # Check that the current page is available in the desired (current) language available_languages = [] # this will return all languages in draft mode, and published only in live mode page_languages = list(page.get_published_languages()) if hasattr(request, 'user') and request.user.is_staff: user_languages = get_language_list() else: user_languages = get_public_languages() for frontend_lang in user_languages: if frontend_lang in page_languages: available_languages.append(frontend_lang) # Check that the language is in FRONTEND_LANGUAGES: own_urls = [ 'http%s://%s%s' % ('s' if request.is_secure() else '', request.get_host(), request.path), '/%s' % request.path, request.path, ] if current_language not in user_languages: #are we on root? if not slug: #redirect to supported language languages = [] for language in available_languages: languages.append((language, language)) if languages: # get supported language new_language = get_language_from_request(request) if new_language in get_public_languages(): with force_language(new_language): pages_root = reverse('pages-root') if (hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode): request.toolbar.redirect_url = pages_root elif pages_root not in own_urls: return HttpResponseRedirect(pages_root) elif not hasattr(request, 'toolbar') or not request.toolbar.redirect_url: _handle_no_page(request, slug) else: return _handle_no_page(request, slug) if current_language not in available_languages: # If we didn't find the required page in the requested (current) # language, let's try to find a fallback found = False for alt_lang in get_fallback_languages(current_language): if alt_lang in available_languages: if get_redirect_on_fallback(current_language) or slug == "": with force_language(alt_lang): path = page.get_absolute_url(language=alt_lang, fallback=True) # In the case where the page is not available in the # preferred language, *redirect* to the fallback page. This # is a design decision (instead of rendering in place)). if (hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode): request.toolbar.redirect_url = path elif path not in own_urls: return HttpResponseRedirect(path) else: found = True if not found and (not hasattr(request, 'toolbar') or not request.toolbar.redirect_url): # There is a page object we can't find a proper language to render it _handle_no_page(request, slug) if apphook_pool.get_apphooks(): # There are apphooks in the pool. Let's see if there is one for the # current page # since we always have a page at this point, applications_page_check is # pointless # page = applications_page_check(request, page, slug) # Check for apphooks! This time for real! app_urls = page.get_application_urls(current_language, False) skip_app = False if (not page.is_published(current_language) and hasattr(request, 'toolbar') and request.toolbar.edit_mode): skip_app = True if app_urls and not skip_app: app = apphook_pool.get_apphook(app_urls) pattern_list = [] if app: for urlpatterns in get_app_urls(app.get_urls(page, current_language)): pattern_list += urlpatterns try: view, args, kwargs = resolve('/', tuple(pattern_list)) return view(request, *args, **kwargs) except Resolver404: pass # Check if the page has a redirect url defined for this language. redirect_url = page.get_redirect(language=current_language) if redirect_url: if (is_language_prefix_patterns_used() and redirect_url[0] == "/" and not redirect_url.startswith('/%s/' % current_language)): # add language prefix to url redirect_url = "/%s/%s" % (current_language, redirect_url.lstrip("/")) # prevent redirect to self if hasattr(request, 'toolbar') and request.user.is_staff and request.toolbar.edit_mode: request.toolbar.redirect_url = redirect_url elif redirect_url not in own_urls: return HttpResponseRedirect(redirect_url) # permission checks if page.login_required and not request.user.is_authenticated(): return redirect_to_login(urlquote(request.get_full_path()), settings.LOGIN_URL) if hasattr(request, 'toolbar'): request.toolbar.set_object(page) response = render_page(request, page, current_language=current_language, slug=slug) return response
def show_menu(context, from_level=0, to_level=100, extra_inactive=0, extra_active=100, template="cms/menu.html", next_page=None, root_id=None): """ render a nested list of all children of the pages from_level: is the start level to_level: is the max level rendered render_children: if set to True will render all not direct ascendants too """ try: # If there's an exception (500), default context_processors may not be called. request = context['request'] except KeyError: return {'template': 'cms/content.html'} page_queryset = get_page_queryset(request) site = Site.objects.get_current() lang = get_language_from_request(request) current_page = request.current_page if current_page == "dummy": context.update({ 'children': [], 'template': template, 'from_level': from_level, 'to_level': to_level, 'extra_inactive': extra_inactive, 'extra_active': extra_active }) return context if hasattr(current_page, "home_pk_cache"): home_pk = current_page.home_pk_cache else: try: home_pk = page_queryset.get_home(site).pk except NoHomeFound: home_pk = 0 if not next_page: #new menu... get all the data so we can save a lot of queries children = [] ancestors = [] alist = None if current_page: alist = current_page.get_ancestors().values_list('id', 'soft_root') if not alist: # == None:# maybe the active node is in an extender? alist = [] extenders = page_queryset.published().filter(in_navigation=True, site=site, level__lte=to_level) extenders = extenders.exclude( navigation_extenders__isnull=True).exclude( navigation_extenders__exact="") for ext in extenders: ext.childrens = [] ext.ancestors_ascending = [] get_extended_navigation_nodes(request, 100, [ext], ext.level, 100, 100, False, ext.navigation_extenders) if hasattr(ext, "ancestor"): alist = list(ext.get_ancestors().values_list( 'id', 'soft_root')) alist = [(ext.pk, ext.soft_root)] + alist break filters = {'in_navigation': True, 'site': site, 'level__lte': to_level} #check the ancestors for softroots soft_root_pk = None for p in alist: ancestors.append(p[0]) if p[1]: soft_root_pk = p[0] #modify filters if we don't start from the root root_page = None if root_id: try: root_page = page_queryset.get(reverse_id=root_id, site=site) except: send_missing_mail(root_id, request) else: if current_page and current_page.soft_root: root_page = current_page soft_root_pk = current_page.pk elif soft_root_pk: root_page = page_queryset.get(pk=soft_root_pk) if root_page: if isinstance(root_page, int): root_page = page_queryset.get(pk=root_page) if isinstance(root_page, Page): root_page = page_queryset.get(pk=root_page.id) elif isinstance(root_page, unicode): root_page = page_queryset.get(reverse_id=root_page, site=site) filters['tree_id'] = root_page.tree_id filters['lft__gt'] = root_page.lft filters['rght__lt'] = root_page.rght filters['level__lte'] = root_page.level + to_level db_from_level = root_page.level + from_level else: db_from_level = from_level if settings.CMS_HIDE_UNTRANSLATED: filters['title_set__language'] = lang if not request.user.is_authenticated(): filters['menu_login_required'] = False pages = page_queryset.published().filter(**filters).order_by( 'tree_id', 'parent', 'lft') pages = list(pages) if root_page: pages = [root_page] + pages all_pages = pages[:] root_level = getattr(root_page, 'level', None) ids = [] current = None for page in pages: # build the tree if current_page and current_page.pk == page.pk: current = page if page.level >= db_from_level: ids.append(page.pk) if page.level == 0 or page.level == root_level: if page.parent_id: page.get_cached_ancestors() else: page.ancestors_ascending = [] page.home_pk_cache = home_pk page.menu_level = 0 - from_level page.childrens = [] children.append(page) if page.pk == soft_root_pk: page.soft_root = False #ugly hack for the recursive function if current_page and not current_page.navigation_extenders: pk = current_page.pk else: pk = -1 find_children(page, pages, extra_inactive, extra_active, ancestors, pk, request=request, to_levels=to_level) if page.pk == soft_root_pk: page.soft_root = True if db_from_level > 0: children = cut_levels(children, db_from_level) titles = list( get_title_queryset(request).filter(page__in=ids, language=lang)) for page in all_pages: # add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title ids.remove(page.pk) if current_page and page.pk == current_page.pk and not getattr( current, 'ancestor', False): page.selected = True if hasattr(page, "childrens"): mark_descendants(page.childrens) if page.pk in ancestors: page.ancestor = True if current_page and page.parent_id == current_page.parent_id and not page.pk == current_page.pk and not getattr( current, 'ancestor', False): page.sibling = True if ids: fallbacks = get_fallback_languages(lang) for l in fallbacks: titles = list( get_title_queryset(request).filter(page__in=ids, language=l)) for page in all_pages: # add the title and slugs and some meta data for title in titles: if title.page_id == page.pk: if not hasattr(page, "title_cache"): page.title_cache = {} page.title_cache[title.language] = title ids.remove(page.pk) if not ids: break children = navigation.handle_navigation_manipulators(children, request) else: children = next_page.childrens context.update({ 'children': children, 'template': template, 'from_level': from_level, 'to_level': to_level, 'extra_inactive': extra_inactive, 'extra_active': extra_active }) return context
def get_fallback_languages_for_page(page, current_language, current_user=None, allowed_languages=None): if allowed_languages is None: allowed_languages = get_languages_for_page_user(page=page, user=current_user) return [language for language in get_fallback_languages(current_language) if language in allowed_languages]
def get_reverse_related_page_extensions(self, model_name, language=None, include_descendants=False): """ Return a query to get the page extensions of a given model type related to the current page extension instance. For example: for an organization, it will return all courses that are pointing to this organization via an OrganizationPlugin in any placeholder of the course page. """ is_draft = self.extended_object.publisher_is_draft # pylint: disable=no-member page_extension = self if is_draft else self.draft_extension page = page_extension.extended_object current_language = language or translation.get_language() site = get_current_site() languages = [current_language] + i18n.get_fallback_languages( current_language, site_id=site.pk) languages = list(dict.fromkeys(languages)) for item in range(len(languages)): for previous_item, previous_language in enumerate(languages[:item + 1]): qop_dict = { "extended_object__placeholders__cmsplugin__language": previous_language } if previous_item == item: if not is_draft: qop_dict.update({ "extended_object__title_set__language": previous_language, "extended_object__title_set__published": True, }) qop = models.Q(**qop_dict) else: qop = ~models.Q(**qop_dict) if previous_item == 0: subclause = qop else: subclause &= qop if item == 0: language_clause = subclause else: language_clause |= subclause self_name = self._meta.model.__name__.lower() if include_descendants is True: bfs = ("extended_object__placeholders__cmsplugin__" f"courses_{self_name:s}pluginmodel__page__node") selector = { f"{bfs:s}__path__startswith": page.node.path, f"{bfs:s}__depth__gte": page.node.depth, } else: bfs = ("extended_object__placeholders__cmsplugin__courses_" f"{self_name:s}pluginmodel__page") selector = {bfs: page} page_extension_model = apps.get_model(app_label="courses", model_name=model_name) # pylint: disable=no-member return (page_extension_model.objects.filter( language_clause, extended_object__publisher_is_draft=is_draft, **selector, ).select_related("extended_object").prefetch_related( models.Prefetch( "extended_object__title_set", to_attr="prefetched_titles", queryset=Title.objects.filter(language=current_language), )).distinct().order_by("extended_object__node__path"))