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. live555源码学习笔记之TaskScheduler

    今天抽空研究了下live555的任务实现: TaskScheduler分为三种任务:socket handler,event handler,delay task.这三种任务的特点是,前两个加入执行队 ...

  2. OpenStack单节点网络设置

    一.上传镜像文件 1.上传镜像 2.检索镜像 二.创建网络 1.创建内部网络 2.创建外部网络 3.创建内部网络子网 设置DHCP分配地址池,点击已创建 4.创建外部网络子网 注意:外部网络与仅主机( ...

  3. 关于解决logging模块写出的日志信息重复的问题

    一般情况下,我们在利用logging模块记录日志的时候,往往会利用下面这种方式进行日志信息的记录: import logging def logger_file(): #生成logger对象 whw_ ...

  4. Jmeter(二十六)Jmeter-Question之“集成Jenkins”

    Jenkins,最初被称为Hudson,是一个Java语言编写的开源持续集成工具.Jenkins在持续集成领域的市场份额居于主导地位,其被各种规模的团队用于各种语言和技术的项目中,比如.net.rub ...

  5. 视角同步NewViewTarget

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

  6. 几种常见NPE

    NPE(Null Point Exception的简称) 1.Map下的NPE 直接上代码: public class User { private Integer id; private Strin ...

  7. POJ 多项式加法

    题解: 采用顺序表.考虑到题目中没有规定指数上界,为避免RE,拟不采用数组.参考了http://blog.csdn.net/inlovecy/article/details/15208473后,最终采 ...

  8. Spring Boot安装及入门实现

    在Eclipse里使用Spring boot,首先需要安装Spring boot的插件STS. 注意:STS插件3.7.0以上版本启动需要JDK1.8 打开Eclipse 菜单栏 Help -> ...

  9. 02 Linux常见命令

    GUI图形界面 图形界面对于我们的Linux系统来说就是一个单独的软件程序,可以安装也可以不用安装: 我们常见的Linux下的常用图形软件为Gnome.KDE.XFce: GLI命令界面 Linux常 ...

  10. HDFS高级功能

    HDFS的六大高级特性: 安全模式 安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除.修改等变更请求.在NameNode主节点启动时,HDFS首先进入安全模式 ...