class ExtendsNode(Node):
must_be_first = True
context_key = 'extends_context' def __init__(self, nodelist, parent_name, template_dirs=None):
self.nodelist = nodelist
self.parent_name = parent_name
self.template_dirs = template_dirs
self.blocks = {n.name: n for n in nodelist.get_nodes_by_type(BlockNode)} def __repr__(self):
return '<ExtendsNode: extends %s>' % self.parent_name.token def find_template(self, template_name, context):
"""
This is a wrapper around engine.find_template(). A history is kept in
the render_context attribute between successive extends calls and
passed as the skip argument. This enables extends to work recursively
without extending the same template twice.
"""
# RemovedInDjango20Warning: If any non-recursive loaders are installed
# do a direct template lookup. If the same template name appears twice,
# raise an exception to avoid system recursion.
for loader in context.template.engine.template_loaders:
if not loader.supports_recursion:
history = context.render_context.setdefault(
self.context_key, [context.template.origin.template_name],
)
if template_name in history:
raise ExtendsError(
"Cannot extend templates recursively when using "
"non-recursive template loaders",
)
template = context.template.engine.get_template(template_name)
history.append(template_name)
return template history = context.render_context.setdefault(
self.context_key, [context.template.origin],
)
template, origin = context.template.engine.find_template(
template_name, skip=history,
)
history.append(origin)
return template def get_parent(self, context):
parent = self.parent_name.resolve(context)
if not parent:
error_msg = "Invalid template name in 'extends' tag: %r." % parent
if self.parent_name.filters or\
isinstance(self.parent_name.var, Variable):
error_msg += " Got this from the '%s' variable." %\
self.parent_name.token
raise TemplateSyntaxError(error_msg)
if isinstance(parent, Template):
# parent is a django.template.Template
return parent
if isinstance(getattr(parent, 'template', None), Template):
# parent is a django.template.backends.django.Template
return parent.template
return self.find_template(parent, context) def render(self, context):
compiled_parent = self.get_parent(context)#获取父模板对象 if BLOCK_CONTEXT_KEY not in context.render_context:
context.render_context[BLOCK_CONTEXT_KEY] = BlockContext()#在context中块上下文,默认词典
block_context = context.render_context[BLOCK_CONTEXT_KEY] # Add the block nodes from this node to the block context
block_context.add_blocks(self.blocks)#为块上下文添加当前页的块。 # If this block's parent doesn't have an extends node it is the root,
# and its block nodes also need to be added to the block context.
for node in compiled_parent.nodelist:
# The ExtendsNode has to be the first non-text node.
if not isinstance(node, TextNode):
if not isinstance(node, ExtendsNode):
blocks = {n.name: n for n in#取得父类中的块节点
compiled_parent.nodelist.get_nodes_by_type(BlockNode)}
block_context.add_blocks(blocks)#使得块节点插到最前面
break # Call Template._render explicitly so the parser context stays
# the same.
return compiled_parent._render(context)#看块节点怎么样render??? @register.tag('extends')
def do_extends(parser, token):#从html文件中生成extend node
"""
Signal that this template extends a parent template. This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
uses the literal value "base" as the name of the parent template to extend,
or ``{% extends variable %}`` uses the value of ``variable`` as either the
name of the parent template to extend (if it evaluates to a string) or as
the parent template itself (if it evaluates to a Template object).
"""
bits = token.split_contents()
if len(bits) != 2:
raise TemplateSyntaxError("'%s' takes one argument" % bits[0])
parent_name = parser.compile_filter(bits[1])#父模板名字
nodelist = parser.parse()#当前html的所有node列表。
if nodelist.get_nodes_by_type(ExtendsNode):
raise TemplateSyntaxError("'%s' cannot appear more than once in the same template" % bits[0])
return ExtendsNode(nodelist, parent_name)
class BlockNode(Node):
def __init__(self, name, nodelist, parent=None):
self.name, self.nodelist, self.parent = name, nodelist, parent def __repr__(self):
return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist) def render(self, context):
block_context = context.render_context.get(BLOCK_CONTEXT_KEY)#从上下文取得块node的信息
with context.push():
if block_context is None:
context['block'] = self
result = self.nodelist.render(context)
else:
push = block = block_context.pop(self.name)#弹出块node,排在后面的先出
if block is None:
block = self
# Create new block so we can store context without thread-safety issues.
block = type(self)(block.name, block.nodelist)
block.context = context
context['block'] = block
result = block.nodelist.render(context)
if push is not None:
block_context.push(self.name, push)
return result

django之block extend标签的更多相关文章

  1. Django 模板继承extend 标签include block

    # block 站网页位置# includ 导入网页标签# extends 导入网页模板 # common_js.html <script src="/static/plugins/j ...

  2. Django内置模板标签

    Django内置标签总览 可以查询下表来总览Django的内置标签: 标签 说明 autoescape 自动转义开关 block 块引用 comment 注释 csrf_token CSRF令牌 cy ...

  3. 第三章:模版层 - 2:Django内置模板标签

    Django内置标签总览 可以查询下表来总览Django的内置标签: 标签 说明 autoescape 自动转义开关 block 块引用 comment 注释 csrf_token CSRF令牌 cy ...

  4. Django项目中模板标签及模板的继承与引用【网站中快速布置广告】

    Django项目中模板标签及模板的继承与引用 常见模板标签 {% static %} {% for x in range(x) %}{% endfor %} 循环的序号{% forloop %} 循环 ...

  5. Django模板语言,标签整理

    Django模板语言 标签 内置标签引用 1. autoescape 控制自动转义是否可用. 这种标签带有任何 on 或 off 作为参数的话,他将决定转义块内效果. 该标签会以一个endautoes ...

  6. Django模板结构优化{% include %}和{% extend %}标签

    https://blog.csdn.net/xujin0/article/details/83420633

  7. django模板 内建标签

    autoescape 控制当前自动转义的行为,有on和off两个选项 {% autoescape on %} {{ body }} {% endautoescape %} block 定义一个子模板可 ...

  8. 测试开发之Django——No6.Django模板中的标签语言

    模板中的标签语言 1.if/else {% if  %} 标签检查(evaluate)一个变量,如果这个变量为真(即:变量存在,非空,不是布尔值假),系统会显示在{% if  %} 和 {% endi ...

  9. 11:django 模板 内建标签

    django 内建标签 autoescape 控制当前自动转义的行为,有on和off两个选项 {% autoescape on %} {{ body }} {% endautoescape %} bl ...

随机推荐

  1. [蓝桥杯]ALGO-16.算法训练_进制转换

    问题描述 我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式.例如:123可表示为 1*102+2*101+3*100这样 ...

  2. C++11--编译器生成的函数

    using namespace std; class Dog {}; /* C++ 03 * 1 默认构造函数(只有当用户没有声明任何构造函数) * 2 拷贝构造(只有当用户没有声明5,6),扩展到C ...

  3. C++进阶--析构函数中的异常

    //############################################################################ /* * 不要让异常离开析构函数 * 析构 ...

  4. Mina 专题

    未完待续>>> 目录: 一)同步.异步.阻塞.非阻塞 二)Java中的NIO 三)Mina 异步请求 四)Mina 同步请求 五)Mina 核心类及处理流程 六)Mina 线程模型 ...

  5. 峰Redis学习(1)Redis简介和安装

    是从博客:http://blog.java1234.com/blog/articles/310.html参考过来的: 第一节:Redis 简介 为什么需要NoSQL,主要应对以下问题,传统关系型数据库 ...

  6. DevOps利器- Hygieia平台开发部署

    前言碎语 Hygieia是什么? Capitalone(全美十大银行之一)开源的DevOps利器.使用Hygieia后,在整个软件开发周期中,用户可以选择VersionOne或Jira进行用户故事的追 ...

  7. 使用 Spring Cloud 和 Docker 构建微服务架构

    如何使用Spring Boot.Spring Cloud.Docker和Netflix的一些开源工具来构建一个微服务架构. 本文通过使用Spring Boot.Spring Cloud和Docker构 ...

  8. etcd安装和所遇到的坑

    首先参照 https://www.cnblogs.com/lyzw/p/6016789.html来安装 虚拟机:VMware® Workstation 12 Pro 系统:CentOS Linux r ...

  9. JDK1.6 Java.lang.Null.Pointer.Exception

    先来看一下JDK1.6的API: NullPointerException (Java Platform SE 6) public class NullPointerException extends ...

  10. HDFS 入门介绍

    HDFS简介 HDFS(Hadoop Distributed File System,Hadoop分布式文件系统),它是一个高度容错性的系统,适合部署在廉价的机器上.HDFS能提供高吞吐量的数据访问, ...