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. 【sql】之case when then else end

    select a.`name`, sum(( END)) '语文', sum(( END)) '数学', sum(( END))'英语' from t_score a GROUP BY a.`name ...

  2. 【剑指offer】规则二维数组查找

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路: ...

  3. P2799国王的魔镜

    链接 想了好久(蒟蒻的不能蒟蒻) 题解: #include<iostream>#include<cstdio>#include<cstring>#include&l ...

  4. java设计模式-工厂系列

    一.简单工厂 1.背景: 任意定制交通工具的类型和生产过程 代码: Moveable.java package com.cy.dp.factory; public interface Moveable ...

  5. 廖雪峰Java5Java集合-5Queue-1使用Queue

    Queue特性和基本方法 Queue实现一个先进先出(FIFO, First In First Out)的队列.如收银台排队支付. Java中LinkedList实现了Queue接口,可以直接把Lin ...

  6. 记录Linux下解压大文件时的一次奇葩经历

    由于需要安装新的系统,使用wget下载tar包,8G多下载了1个多小时.解压完后的文件夹中的tar包数量明显不够,而且原始的tar包竟然不见了. 同样的操作又进行了一次,结果还是一样,不得不怀疑是哪里 ...

  7. angular的subscribe

    angular中可以使用observable和subscribe实现订阅,从而实现异步. 这里记录一个工作中的小问题,以加深对subscribe的理解.前端技能弱,慢慢积累中. 本来希望的是点击一个按 ...

  8. datetime模块常用功能小结

  9. [UE4]裁剪 Clipping

    Clipping裁剪,是每个UI都有的属性.一般是在容器UI上设置,对容器内的UI进行裁剪. 一.Clip to Bounds:裁剪到边界 二.Clip To Bounds - Without Int ...

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

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