django的模板编译后变成一般text、tag、varible,然后根据上下文进行渲染。

class ForNode(Node):
    child_nodelists = ('nodelist_loop', 'nodelist_empty')

def __init__(self, loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty=None):
        self.loopvars, self.sequence = loopvars, sequence
        self.is_reversed = is_reversed
        self.nodelist_loop = nodelist_loop
        if nodelist_empty is None:
            self.nodelist_empty = NodeList()
        else:
            self.nodelist_empty = nodelist_empty

def __repr__(self):
        reversed_text = ' reversed' if self.is_reversed else ''
        return "<For Node: for %s in %s, tail_len: %d%s>" % \
            (', '.join(self.loopvars), self.sequence, len(self.nodelist_loop),
             reversed_text)

def __iter__(self):
        for node in self.nodelist_loop:
            yield node
        for node in self.nodelist_empty:
            yield node

def render(self, context):
        if 'forloop' in context:#先判断是不是for循环
            parentloop = context['forloop']
        else:
            parentloop = {}
        with context.push():#调用context.push()会在栈顶放一个contextdict对象
            try:
                values = self.sequence.resolve(context, True)#找到可迭代的对象
            except VariableDoesNotExist:
                values = []
            if values is None:
                values = []
            if not hasattr(values, '__len__'):
                values = list(values)
            len_values = len(values)
            if len_values < 1:
                return self.nodelist_empty.render(context)
            nodelist = []
            if self.is_reversed:
                values = reversed(values)
            num_loopvars = len(self.loopvars)#判断loop变量个数
            unpack = num_loopvars > 1
            # Create a forloop value in the context.  We'll update counters on each
            # iteration just below.
            loop_dict = context['forloop'] = {'parentloop': parentloop}#loop_dict与context['forloop']是同一个词典,loop_dict['counter0'] = i后,通过context['forloop']可以访问到loop_dict
            for i, item in enumerate(values):
                # Shortcuts for current loop iteration number.
                loop_dict['counter0'] = i#每次循环时counter0的值都会变化,可以在模板文件上使用
                loop_dict['counter'] = i + 1
                # Reverse counter iteration numbers.
                loop_dict['revcounter'] = len_values - i
                loop_dict['revcounter0'] = len_values - i - 1
                # Boolean values designating first and last times through loop.
                loop_dict['first'] = (i == 0)
                loop_dict['last'] = (i == len_values - 1)

pop_context = False
                if unpack:
                    # If there are multiple loop variables, unpack the item into
                    # them.

# To complete this deprecation, remove from here to the
                    # try/except block as well as the try/except itself,
                    # leaving `unpacked_vars = ...` and the "else" statements.
                    if not isinstance(item, (list, tuple)):
                        len_item = 1
                    else:
                        len_item = len(item)
                    # Check loop variable count before unpacking
                    if num_loopvars != len_item:
                        warnings.warn(
                            "Need {} values to unpack in for loop; got {}. "
                            "This will raise an exception in Django 1.10."
                            .format(num_loopvars, len_item),
                            RemovedInDjango110Warning)
                    try:
                        unpacked_vars = dict(zip(self.loopvars, item))
                    except TypeError:
                        pass
                    else:
                        pop_context = True
                        context.update(unpacked_vars)
                else:
                    context[self.loopvars[0]] = item#在上下文中增加变量,为后面的node渲染提供数据

for node in self.nodelist_loop:
                    nodelist.append(node.render_annotated(context))

if pop_context:
                    # The loop variables were pushed on to the context so pop them
                    # off again. This is necessary because the tag lets the length
                    # of loopvars differ to the length of each set of items and we
                    # don't want to leave any vars from the previous loop on the
                    # context.
                    context.pop()
        return mark_safe(''.join(force_text(n) for n in nodelist))

context每次调用push函数后都会改变context的dicts列表。解析一个node时,都会有一个上下文。相当于一个新的环境。

django之ForNode是如何渲染的的更多相关文章

  1. Django基础学习六之渲染

    今天简单的介绍一下Django的template的渲染和Django的template的基本的语法 首先我们先启动一个django的shell,首先需要进入django的工程目录下启动django的s ...

  2. Django学习笔记之模板渲染、模板语言、simple_tag、母版子版、静态配置文件

    一.首先我们用PyCharm来创建一个Django项目 终端命令:django-admin startproject sitename 图形创建:   这样一个Django项目就创建完成了,上面可以看 ...

  3. Django 命令行调用模版渲染

    首先我们需要进入 Django 的 shell python manage.py shell 渲染模版中的 name from django.template import Context,Templ ...

  4. Django路由分配以及模版渲染

    路由上: 在网络上区分不同的电脑通过IP.端口和网卡的MAC地址等,在web框架中怎么区分不同的请求呢,就是通过 ‘url(路由)’ ,url 学名叫做全球统一资源定位符,其实就是一个网址 一个url ...

  5. django 第四天模板渲染

    今日内容 一.模板渲染 语法 {{ 变量 }} {% 逻辑 %} 1.变量 取列表中的第几个元素,用索引 <p>{{ namelist.2 }}</p> 取字典中的第几个元素用 ...

  6. 「Django」rest_framework学习系列-渲染器

    渲染器:作用于页面,JSONRenderer只是JSON格式,BrowsableAPIRenderer有页面,.AdminRenderer页面以admin形式呈现(需要在请求地址后缀添加?fromat ...

  7. Django rest-framework框架-组件之渲染器

    渲染器: from rest_framework.renderers import BrowsableAPIRenderer,AdminRenderer,HTMLFormRenderer,JSONRe ...

  8. Django(51)drf渲染模块源码分析

    前言 渲染模块的原理和解析模块是一样,drf默认的渲染有2种方式,一种是json格式,另一种是模板方式. 渲染模块源码入口 入口:APIView类中dispatch方法中的:self.response ...

  9. Django学习路29_css样式渲染 h3 标签

    在 static 静态文件夹下创建 css 文件夹 home.css 此时 home.css 路径是 'static/css/home.css' 在 对应的 home.html 文件中添加 css 样 ...

随机推荐

  1. SpringSecurity的Filter执行顺序在源码中的体现

    在网上看各种SpringSecurity教程时,都讲到了SpringSecurity的Filter顺序.但是一直不知道这个顺序在源码中是如何体现的.今天一步一步的查找,最终找到顺序是在FilterCo ...

  2. console输出选择器的问题

    html代码: <input type="text" class="loginInput loginPwText gray" value="密码 ...

  3. Java zxing生成二维码所需的jar包

    免费的,不需要积分. 共有2个jar包, 链接: https://pan.baidu.com/s/1QJcEkRQOp1NdrNAgGC6LvQ 密码: 4524

  4. Jmeter(二十一)Jmeter常见问题及场景应用

    Jmeter作为工具来讲,已经是一个相对比较牛掰的工具,除了它能够支持那么多协议以及方法之外,更在与它的前置处理以及后置处理.同步监控的人性化.当然,所有的工具.框架都是作为业务的支撑,如果不能满足我 ...

  5. UE4 几个好用的插件和Wiki教程

    转自:http://blog.csdn.net/u014532636/article/details/72729881 https://github.com/ue4plugins/LoadingScr ...

  6. (转)Linux中设置服务自启动的三种方式

    有时候我们需要Linux系统在开机的时候自动加载某些脚本或系统服务 主要用三种方式进行这一操作: ln -s                       在/etc/rc.d/rc*.d目录中建立/e ...

  7. vue808

    自定义键盘信息:    Vue.directive('on').keyCodes.ctrl=17;    Vue.directive('on').keyCodes.myenter=13; 数据深度监听 ...

  8. python3基础操作

    ubuntu下python连接mysql apt-get install python-mysqldb 获取当前时间 >>> from datetime import datetim ...

  9. MySQL查询表的所有列名,用逗号拼接

    问题场景 在MySQL中,需要以逗号拼接一个表的所有字段 sql语句 SELECT GROUP_CONCAT(COLUMN_NAME SEPARATOR ",") FROM inf ...

  10. 《Linux 性能及调优指南》1.6 了解Linux性能指标

    翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...