def _page_has_appcontent(page): # Very dumb implementation, will be overridden with a more efficient # version if ct_tracker is enabled. applicationcontents = page.applicationcontent_set.all() has_appcontent = any(applicationcontents) return has_appcontent
def _page_has_appcontent(page): # Very dumb implementation, will be overridden with a more efficient # version if ct_tracker is enabled. try: applicationcontents = page.applicationcontent_set.all() except AttributeError: return False has_appcontent = any(applicationcontents) return has_appcontent
def siblings_along_path_to(page_list, page2): """ Filters a list of pages so that only those remain that are either: * An ancestor of the current page * A sibling of an ancestor of the current page A typical use case is building a navigation menu with the active path to the current page expanded:: {% feincms_navigation of feincms_page as navitems level=1,depth=3 %} {% with navitems|siblings_along_path_to:feincms_page as navtree %} ... whatever ... {% endwith %} """ try: # Try to avoid hitting the database: If the current page is in_navigation, # then all relevant pages are already in the incoming list, no need to # fetch ancestors or children. # NOTE: This assumes that the input list actually is complete (ie. comes from # feincms_navigation). We'll cope with the fall-out of that assumption # when it happens... ancestors = [ a_page for a_page in page_list if _is_equal_or_parent_of(a_page, page2) ] if not ancestors: # Happens when we sit on a page outside the navigation tree # so fake an active root page to avoid a get_ancestors() db call # which would only give us a non-navigation root page anyway. p = Page(title="dummy", tree_id=-1, parent_id=None, in_navigation=False) ancestors = (p, ) siblings = [ a_page for a_page in page_list if a_page.parent_id == page2.id or any((_is_sibling_of(a_page, a) for a in ancestors)) ] return siblings except AttributeError: return ()
def all_of_type(self, type_or_tuple): """ Return all content type instances belonging to the type or types passed. If you want to filter for several types at the same time, type must be a tuple. """ content_list = [] if not hasattr(type_or_tuple, '__iter__'): type_or_tuple = (type_or_tuple,) self._popuplate_content_type_caches(type_or_tuple) for type, contents in self._cache['cts'].items(): if any(issubclass(type, t) for t in type_or_tuple): content_list.extend(contents) # TODO: Sort content types by region? return sorted(content_list, key=lambda c: c.ordering)
def build_page_response(page, request): from django.core.cache import cache as django_cache # Try to avoid the lookup of app contents by caching, since nodes # with app content are a rather rare occurrence, this is a win in # most cases. has_appcontent = True if settings.FEINCMS_USE_CACHE: ck = 'HAS-APP-CONTENT-' + page.cache_key() has_appcontent = django_cache.get(ck, True) if has_appcontent: applicationcontents = page.applicationcontent_set.all() has_appcontent = any(applicationcontents) if settings.FEINCMS_USE_CACHE: django_cache.set(ck, has_appcontent) if request.path != page.get_absolute_url(): # The best_match logic kicked in. See if we have at least one # application content for this page, and raise a 404 otherwise. if not has_appcontent: raise Http404 else: request._feincms_appcontent_parameters['in_appcontent_subpage'] = True # The monkey-patched reverse() method needs some information # for proximity analysis when determining the nearest # application integration point retrieve_page_information(page) response = page.setup_request(request) if response: return response if has_appcontent: for content in applicationcontents: r = content.process(request) if r and (r.status_code != 200 or request.is_ajax() or getattr(r, 'standalone', False)): return r response = _build_page_response(page, request) page.finalize_response(request, response) return response
def _content_for_region(self, region): """ This method is used primarily by the ContentProxy """ self._needs_content_types() counts = self._get_content_types_for_region(region) if not any(counts): return [] contents = [] for idx, cnt in enumerate(counts): if cnt: # the queryset is evaluated right here, because the content objects # of different type will have to be sorted into a list according # to their 'ordering' attribute later contents += list(self._feincms_content_types[idx].get_queryset( Q(parent=self) & Q(region=region.key))) return contents
def _content_for_region(self, region): """ This method is used primarily by the ContentProxy """ self._needs_content_types() counts = self._get_content_types_for_region(region) if not any(counts): return [] contents = [] for idx, cnt in enumerate(counts): if cnt: # the queryset is evaluated right here, because the content objects # of different type will have to be sorted into a list according # to their 'ordering' attribute later contents += list( self._feincms_content_types[idx].get_queryset( Q(parent=self) & Q(region=region.key))) return contents
def siblings_along_path_to(page_list, page2): """ Filters a list of pages so that only those remain that are either: * An ancestor of the current page * A sibling of an ancestor of the current page A typical use case is building a navigation menu with the active path to the current page expanded:: {% feincms_navigation of feincms_page as navitems level=1,depth=3 %} {% with navitems|siblings_along_path_to:feincms_page as navtree %} ... whatever ... {% endwith %} """ try: # Try to avoid hitting the database: If the current page is in_navigation, # then all relevant pages are already in the incoming list, no need to # fetch ancestors or children. # NOTE: This assumes that the input list actually is complete (ie. comes from # feincms_navigation). We'll cope with the fall-out of that assumption # when it happens... ancestors = [a_page for a_page in page_list if _is_equal_or_parent_of(a_page, page2)] if not ancestors: # Happens when we sit on a page outside the navigation tree # so fake an active root page to avoid a get_ancestors() db call # which would only give us a non-navigation root page anyway. p = Page(title="dummy", tree_id=-1, parent_id=None, in_navigation=False) ancestors = (p,) siblings = [a_page for a_page in page_list if a_page.parent_id == page2.id or any((_is_sibling_of(a_page, a) for a in ancestors))] return siblings except AttributeError: return ()
def _content_for_region(self, region): """ This method is used primarily by the ContentProxy """ self._needs_content_types() from django.core.cache import cache as django_cache counts = None ck = None # ???: Should we move the cache_key() method to Base, so we can avoid # the if-it-supports-it dance? if settings.FEINCMS_USE_CACHE and getattr(self, 'cache_key', None): ck = 'CNT-FOR-REGION-' + region.key + '-' + self.cache_key() counts = django_cache.get(ck) if counts is None: counts = self._get_content_types_for_region(region) if ck: django_cache.set(ck, counts) if not any(counts): return [] contents = [] for idx, cnt in enumerate(counts): if cnt: # the queryset is evaluated right here, because the content objects # of different type will have to be sorted into a list according # to their 'ordering' attribute later contents += list( self._feincms_content_types[idx].objects.filter( parent=self, region=region.key).select_related()) # Note: the select_related() helps for content types that # reference stuff (eg. media files) and doesn't hurt much # when not needed. return contents
def _content_for_region(self, region): """ This method is used primarily by the ContentProxy """ self._needs_content_types() # find all concrete content type tables which have at least one entry for # the current CMS object and region sql = ' UNION '.join([ 'SELECT %d AS ct_idx, COUNT(id) FROM %s WHERE parent_id=%s AND region=%%s' % ( idx, cls._meta.db_table, self.pk) for idx, cls in enumerate(self._feincms_content_types)]) sql = 'SELECT * FROM ( ' + sql + ' ) AS ct ORDER BY ct_idx' from django.db import connection cursor = connection.cursor() cursor.execute(sql, [region.key] * len(self._feincms_content_types)) counts = [row[1] for row in cursor.fetchall()] if not any(counts): return [] contents = [] for idx, cnt in enumerate(counts): if cnt: # the queryset is evaluated right here, because the content objects # of different type will have to be sorted into a list according # to their 'ordering' attribute later contents += list( self._feincms_content_types[idx].objects.filter( parent=self, region=region.key).select_related('parent', 'region')) return contents
def is_feincms_test(): return any('feincms' in arg for arg in sys.argv[2:])