def splat_handler(request, splat): slugs = filter(lambda x: x, splat.split("/")) current_node = topicdata.TOPICS seeking = "Topic" # search for topics, until we find videos or exercise for slug in slugs: # towards the end of the url, we switch from seeking a topic node # to the particular type of node in the tree for kind, kind_slug in topic_tools.kind_slugs.items(): if slug == kind_slug.split("/")[0]: seeking = kind break # match each step in the topics hierarchy, with the url slug. else: children = [child for child in current_node['children'] if child['kind'] == seeking] if not children: raise Http404 match = None prev = None next = None for child in children: if match: next = child break if child["slug"] == slug: match = child else: prev = child if not match: raise Http404 current_node = match if current_node["kind"] == "Topic": return topic_handler(request, cached_nodes={"topic": current_node}) elif current_node["kind"] == "Video": return video_handler(request, cached_nodes={"video": current_node, "prev": prev, "next": next}) elif current_node["kind"] == "Exercise": cached_nodes = topic_tools.get_related_videos(current_node, limit_to_available=False) cached_nodes["exercise"] = current_node return exercise_handler(request, cached_nodes=cached_nodes) else: raise Http404
def refresh_topic_cache_wrapper_fn(request, cached_nodes={}, force=False, *args, **kwargs): """ Centralized logic for how to refresh the topic cache, for each type of object. When the object is desired to be used, this code runs to refresh data, balancing between correctness and efficiency. """ if not cached_nodes: cached_nodes = {"topics": topicdata.TOPICS} for node in cached_nodes.values(): if not node: continue has_children = bool(node.get("children")) # Propertes not yet marked if node["kind"] == "Video": if force or "availability" not in node: #stamp_availability_on_topic(node, force=force) # will be done by force below recount_videos_and_invalidate_parents(get_parent(node), force=True, stamp_urls=True) elif node["kind"] == "Exercise": for video in topic_tools.get_related_videos(exercise=node).values(): if not "availability" in video: stamp_availability_on_video(video, force=True) # will be done by force below elif node["kind"] == "Topic": bottom_layer_topic = "Topic" not in node["contains"] # always run video_counts_need_update(), to make sure the (internal) counts stay up to date. force = video_counts_need_update() or force or bottom_layer_topic recount_videos_and_invalidate_parents( node, force=force, stamp_urls=bottom_layer_topic, ) kwargs.update(cached_nodes) return handler(request, *args, **kwargs)
def splat_handler(request, splat): slugs = filter(lambda x: x, splat.split("/")) current_node = topicdata.TOPICS while current_node: match = [ch for ch in (current_node.get('children') or []) if request.path.startswith(ch["path"])] if not match: raise Http404 current_node = match[0] if request.path == current_node["path"]: break if current_node["kind"] == "Topic": return topic_handler(request, cached_nodes={"topic": current_node}) elif current_node["kind"] == "Video": prev, next = get_neighbor_nodes(current_node, neighbor_kind=current_node["kind"]) return video_handler(request, cached_nodes={"video": current_node, "prev": prev, "next": next}) elif current_node["kind"] == "Exercise": cached_nodes = topic_tools.get_related_videos(current_node, limit_to_available=False) cached_nodes["exercise"] = current_node cached_nodes["prev"], cached_nodes["next"] = get_neighbor_nodes(current_node, neighbor_kind=current_node['kind']) return exercise_handler(request, cached_nodes=cached_nodes) else: raise Http404