mezzanine的head 导航条、左侧tree、footer是由page_menu产生的。page_menu的算法,先计算出每一页的孩子,然后再逐页去page_menu。

@register.render_tag
def page_menu(context, token):
"""
Return a list of child pages for the given parent, storing all
pages in a dict in the context when first called using parents as keys
for retrieval on subsequent recursive calls from the menu template.
"""
# First arg could be the menu template file name, or the parent page.
# Also allow for both to be used.
template_name = None
parent_page = None
parts = token.split_contents()[1:]#对page_menu菜单分离,取得参数
for part in parts:
part = Variable(part).resolve(context)
if isinstance(part, str):
template_name = part#文本为模板名
elif isinstance(part, Page):
parent_page = part#父页
if template_name is None:#没有提供模板的话,从上下文中获取
try:
template_name = context["menu_template_name"]
except KeyError:
error = "No template found for page_menu in: %s" % parts
raise TemplateSyntaxError(error)
context["menu_template_name"] = template_name#设置模板
if "menu_pages" not in context:#没有菜单页,取得当前用户有权访问的页
try:
user = context["request"].user
slug = context["request"].path
except KeyError:
user = None
slug = ""
num_children = lambda id: lambda: len(context["menu_pages"][id])#匿名函数,函数中包含函数
has_children = lambda id: lambda: num_children(id)() > 0
rel = [m.__name__.lower()#取得Page的子类,但不包括Page自身
for m in Page.get_content_models()
if not m._meta.proxy]
published = Page.objects.published(for_user=user).select_related(*rel)#把相关联的model也进行查询
# Store the current page being viewed in the context. Used
# for comparisons in page.set_menu_helpers.
if "page" not in context:
try:
context.dicts[0]["_current_page"] = published.exclude(
content_model="link").get(slug=slug)
except Page.DoesNotExist:
context.dicts[0]["_current_page"] = None
elif slug:
context.dicts[0]["_current_page"] = context["page"]#记录当前页
# Some homepage related context flags. on_home is just a helper
# indicated we're on the homepage. has_home indicates an actual
# page object exists for the homepage, which can be used to
# determine whether or not to show a hard-coded homepage link
# in the page menu.
home = home_slug()
context.dicts[0]["on_home"] = slug == home
context.dicts[0]["has_home"] = False
# Maintain a dict of page IDs -> parent IDs for fast
# lookup in setting page.is_current_or_ascendant in
# page.set_menu_helpers.
context.dicts[0]["_parent_page_ids"] = {}#保存父页id的词典
pages = defaultdict(list)#pages[]不存在时,不会出错,返回[]
for page in published.order_by("_order"):
page.set_helpers(context)#判断是否是当前页,有无孩子
context["_parent_page_ids"][page.id] = page.parent_id#各页的父
setattr(page, "num_children", num_children(page.id))
setattr(page, "has_children", has_children(page.id))
pages[page.parent_id].append(page)#取得各页的子页list
if page.slug == home:
context.dicts[0]["has_home"] = True
# Include menu_pages in all contexts, not only in the
# block being rendered.
context.dicts[0]["menu_pages"] = pages
# ``branch_level`` must be stored against each page so that the
# calculation of it is correctly applied. This looks weird but if we do
# the ``branch_level`` as a separate arg to the template tag with the
# addition performed on it, the addition occurs each time the template
# tag is called rather than once per level.
context["branch_level"] = 0#默认层次为0
parent_page_id = None
if parent_page is not None:
context["branch_level"] = getattr(parent_page, "branch_level", 0) + 1
parent_page_id = parent_page.id # Build the ``page_branch`` template variable, which is the list of
# pages for the current parent. Here we also assign the attributes
# to the page object that determines whether it belongs in the
# current menu template being rendered.
context["page_branch"] = context["menu_pages"].get(parent_page_id, [])#取得该页的子页
context["page_branch_in_menu"] = False
for page in context["page_branch"]:#处理该分支
page.in_menu = page.in_menu_template(template_name)#判断是否在该菜单
page.num_children_in_menu = 0
if page.in_menu:
context["page_branch_in_menu"] = True
for child in context["menu_pages"].get(page.id, []):
if child.in_menu_template(template_name):
page.num_children_in_menu += 1
page.has_children_in_menu = page.num_children_in_menu > 0
page.branch_level = context["branch_level"]
page.parent = parent_page
context["parent_page"] = page.parent # Prior to pages having the ``in_menus`` field, pages had two
# boolean fields ``in_navigation`` and ``in_footer`` for
# controlling menu inclusion. Attributes and variables
# simulating these are maintained here for backwards
# compatibility in templates, but will be removed eventually.
page.in_navigation = page.in_menu
page.in_footer = not (not page.in_menu and "footer" in template_name)
if page.in_navigation:
context["page_branch_in_navigation"] = True
if page.in_footer:
context["page_branch_in_footer"] = True t = get_template(template_name)
return t.render(Context(context))

mezzanine的page_menu tag的更多相关文章

  1. mezzanine的page_menu tag(二)

    dict的特性,key可以是None >>> def f(): a=[2,3] return a #函数返回local变量 >>> a=f() >>&g ...

  2. mezzanine的breadcrumb

    page_menu tag为什么能渲染出当前页的面包屑路径??靠的是request的page对象,要是page的自己或是它的的祖先才渲染,是根据page的属性page.is_current_or_as ...

  3. mezzanine的page表

    class Orderable(with_metaclass(OrderableBase, models.Model)): """ Abstract model that ...

  4. Git 进阶指南(git ssh keys / reset / rebase / alias / tag / submodule )

    在掌握了基础的 Git 使用 之后,可能会遇到一些常见的问题.以下是猫哥筛选总结的部分常见问题,分享给各位朋友,掌握了这些问题的中的要点之后,git 进阶也就完成了,它包含以下部分: 如何修改 ori ...

  5. 05.GitHub实战系列~5.发布版本之分支操作+Tag讲解 2015-12-14

    GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...

  6. Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with value '"*, Microsoft.AspNet.Mvc.TagHelpers"'

    project.json 配置: { "version": "1.0.0-*", "compilationOptions": { " ...

  7. ASP.NET Core 中文文档 第四章 MVC(3.6.1 )Tag Helpers 介绍

    原文:Introduction to Tag Helpers 作者:Rick Anderson 翻译:刘浩杨 校对:高嵩(Jack) 什么是 Tag Helpers? Tag Helpers 提供了什 ...

  8. ASP.NET Core 中文文档 第四章 MVC(3.6.2 )自定义标签辅助类(Tag Helpers)

    原文:Authoring Tag Helpers 作者:Rick Anderson 翻译:张海龙(jiechen) 校对:许登洋(Seay) 示例代码查看与下载 从 Tag Helper 讲起 本篇教 ...

  9. VS2015突然报错————Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with value 'Microsoft.AspNet.Mvc.Razor.TagHelpers.UrlResolutionTagHelper

    Encountered an unexpected error when attempting to resolve tag helper directive '@addTagHelper' with ...

随机推荐

  1. Java多线程编程——并发编程原理(分布式环境中并发问题)

    在分布式环境中,处理并发问题就没办法通过操作系统和JVM的工具来解决,那么在分布式环境中,可以采取一下策略和方式来处理: 避免并发 时间戳 串行化 数据库 行锁 统一触发途径 避免并发 在分布式环境中 ...

  2. boost::asio::io_context类

    //有个疑惑: 向io_context对象中提交的任务只能被顺序化的执行. //下面这个构造函数表明可以运行多线程啊..... /** * Construct with a hint about th ...

  3. hadoop fs、hadoop dfs与hdfs dfs的区别

    不多说,直接上干货! hadoop fs:    使用面最广,可以操作任何文件系统. hadoop dfs与hdfs dfs :   只能操作HDFS文件系统相关(包括与Local FS间的操作),前 ...

  4. 1125 Chain the Ropes (25 分)

    1125 Chain the Ropes (25 分) Given some segments of rope, you are supposed to chain them into one rop ...

  5. 视角同步NewViewTarget

    SetViewTargetwithBlen说明: http://api.unrealengine.com/INT/BlueprintAPI/Game/Player/SetViewTargetwithB ...

  6. Rehash死锁的问题

    为什么都说HashMap是线程不安全的呢?它在多线程环境下,又会发生什么情况呢? resize死循环 我们都知道HashMap的初始容量是16,一般来说,当插入数据时,都会检查容量有没有超过设定的th ...

  7. AD中组的概念

  8. maven的web项目和shiro集成的问题

    在自定义shiro然后在加入spring的配置文件时,启动tomcat的时候一直报错 原因:刚学,对maven的依赖构建属性不熟悉 只是完成了maven父项目和子项目的依赖关系,并没有配置子项目之间的 ...

  9. Python的可迭代对象、迭代器和生成器

    可迭代对象(Iterable) 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable. 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.t ...

  10. Spring IoC中各个注解的理解和使用

    一.把在Spring的xml文件中配置bean改为Spring的注解来配置bean 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点:1.如果所有的 ...