context作为view与template之间的桥梁,理解它的工作原理对于djagno的模板工作机制至关重要。

class ContextDict(dict):#上下文词典,由词典可以通过context找到属于那个上下文,dicts是列表
def __init__(self, context, *args, **kwargs):
super(ContextDict, self).__init__(*args, **kwargs) context.dicts.append(self)
self.context = context def __enter__(self):
return self def __exit__(self, *args, **kwargs):
self.context.pop()

class ContextDict(dict)是用来保存数据的,它连接了context与dicts,该类可以作为with语句表达式。

class BaseContext(object):#上下文的基类
def __init__(self, dict_=None):
self._reset_dicts(dict_) def _reset_dicts(self, value=None):#每个上下文都是以builtins作为第一个元素的
builtins = {'True': True, 'False': False, 'None': None}
self.dicts = [builtins]
if value is not None:
self.dicts.append(value) def __copy__(self):
duplicate = copy(super(BaseContext, self))
duplicate.dicts = self.dicts[:]
return duplicate def __repr__(self):
return repr(self.dicts) def __iter__(self):
for d in reversed(self.dicts):
yield d def push(self, *args, **kwargs):#调用push时会生成一个上下文词典
dicts = []
for d in args:
if isinstance(d, BaseContext):
dicts += d.dicts[1:]
else:
dicts.append(d)
return ContextDict(self, *dicts, **kwargs) def pop(self):
if len(self.dicts) == 1:
raise ContextPopException
return self.dicts.pop() def __setitem__(self, key, value):#执行context['var']=var时,是在dicts的最后一个元素添加。
"Set a variable in the current context"
self.dicts[-1][key] = value def __getitem__(self, key):#从最后一个元素开始查找key对应的值
"Get a variable's value, starting at the current context and going upward"
for d in reversed(self.dicts):
if key in d:
return d[key]
raise KeyError(key) def __delitem__(self, key):
"Delete a variable from the current context"
del self.dicts[-1][key] def has_key(self, key):
for d in self.dicts:
if key in d:
return True
return False def __contains__(self, key):
return self.has_key(key) def get(self, key, otherwise=None):
for d in reversed(self.dicts):
if key in d:
return d[key]
return otherwise def setdefault(self, key, default=None):
try:
return self[key]
except KeyError:
self[key] = default
return default def new(self, values=None):
"""
Returns a new context with the same properties, but with only the
values given in 'values' stored.
"""
new_context = copy(self)
new_context._reset_dicts(values)
return new_context def flatten(self):
"""
Returns self.dicts as one dictionary
"""
flat = {}
for d in self.dicts:
flat.update(d)
return flat def __eq__(self, other):
"""
Compares two contexts by comparing theirs 'dicts' attributes.
"""
if isinstance(other, BaseContext):
# because dictionaries can be put in different order
# we have to flatten them like in templates
return self.flatten() == other.flatten() # if it's not comparable return false
return False

class Context(BaseContext):

class RequestContext(Context):

class RenderContext(BaseContext):

Context 与RequestContext的区别:

def __init__(self, dict_=None, autoescape=True,
            current_app=_current_app_undefined,
            use_l10n=None, use_tz=None):

def __init__(self, request, dict_=None, processors=None,
            current_app=_current_app_undefined,
            use_l10n=None, use_tz=None):

由它们的初始化函数的参数来看RenderContext多了一个request,processors,少了autoescape。

Context的update函数分析:

def update(self, other_dict):
        "Pushes other_dict to the stack of dictionaries in the Context"
        if not hasattr(other_dict, '__getitem__'):
            raise TypeError('other_dict must be a mapping (dictionary-like) object.')
        if isinstance(other_dict, BaseContext):#如果other_dict是上下文实例,要把头与尾去掉,重新生成上下文词典
            other_dict = other_dict.dicts[1:].pop()
        return ContextDict(self, other_dict)

模板上下文处理器在什么地方调用?在调用结果如何影响context?

class RequestContext(Context):
"""
This subclass of template.Context automatically populates itself using
the processors defined in the engine's configuration.
Additional processors can be specified as a list of callables
using the "processors" keyword argument.
"""
def __init__(self, request, dict_=None, processors=None,
current_app=_current_app_undefined,
use_l10n=None, use_tz=None):
# current_app isn't passed here to avoid triggering the deprecation
# warning in Context.__init__.
super(RequestContext, self).__init__(
dict_, use_l10n=use_l10n, use_tz=use_tz)
if current_app is not _current_app_undefined:
warnings.warn(
"The current_app argument of RequestContext is deprecated. "
"Set the current_app attribute of its request instead.",
RemovedInDjango110Warning, stacklevel=2)
self._current_app = current_app
self.request = request
self._processors = () if processors is None else tuple(processors)
self._processors_index = len(self.dicts) # placeholder for context processors output
self.update({}) # empty dict for any new modifications
# (so that context processors don't overwrite them)
self.update({}) @contextmanager
def bind_template(self, template):#绑定模板时会调用全局的上下文处理器及该请求的。
if self.template is not None:
raise RuntimeError("Context is already bound to a template") self.template = template
# Set context processors according to the template engine's settings.
processors = (template.engine.template_context_processors +
self._processors)
updates = {}
for processor in processors:
updates.update(processor(self.request))#每个处理器返回一个词典,通过调用词典的更新函数进行合并
self.dicts[self._processors_index] = updates#self._processors_index为len(self.dicts) try:
yield
finally:
self.template = None
# Unset context processors.
self.dicts[self._processors_index] = {} def new(self, values=None):
new_context = super(RequestContext, self).new(values)
# This is for backwards-compatibility: RequestContexts created via
# Context.new don't include values from context processors.
if hasattr(new_context, '_processors_index'):
del new_context._processors_index
return new_context
C:\mez>python manage.py shell
Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] In [1]: from django.template import context In [3]: dir(context)
Out[3]:
['BaseContext',
'Context',
'ContextDict',
'ContextPopException',
'RemovedInDjango110Warning',
'RenderContext',
'RequestContext',
'__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'_builtin_context_processors',
'_current_app_undefined',
'contextmanager',
'copy',
'make_context',
'warnings'] In [4]: c=context.Context() In [5]: c.__dict__
Out[5]:
{'_current_app': <object at 0x1597d08>,
'autoescape': True,
'dicts': [{'False': False, 'None': None, 'True': True}],
'render_context': [{'False': False, 'None': None, 'True': True}],
'template': None,
'template_name': 'unknown',
'use_l10n': None,
'use_tz': None} In [6]: c.push()
Out[6]: {} In [7]: c.__dict__
Out[7]:
{'_current_app': <object at 0x1597d08>,
'autoescape': True,
'dicts': [{'False': False, 'None': None, 'True': True}, {}],
'render_context': [{'False': False, 'None': None, 'True': True}],
'template': None,
'template_name': 'unknown',
'use_l10n': None,
'use_tz': None} In [8]: c['page']='welcome' In [9]: c.__dict__
Out[9]:
{'_current_app': <object at 0x1597d08>,
'autoescape': True,
'dicts': [{'False': False, 'None': None, 'True': True}, {'page': 'welcome'}],
'render_context': [{'False': False, 'None': None, 'True': True}],
'template': None,
'template_name': 'unknown',
'use_l10n': None,
'use_tz': None} In [10]: c['menu']='menus' In [11]: c.__dict__
Out[11]:
{'_current_app': <object at 0x1597d08>,
'autoescape': True,
'dicts': [{'False': False, 'None': None, 'True': True},
{'menu': 'menus', 'page': 'welcome'}],
'render_context': [{'False': False, 'None': None, 'True': True}],
'template': None,
'template_name': 'unknown',
'use_l10n': None,
'use_tz': None} In [12]: c['page']
Out[12]: 'welcome' In [13]: d={1:2,3:4} In [14]: c['d']=d In [16]: c['d']
Out[16]: {1: 2, 3: 4} In [17]: c.push(d)
Out[17]: {1: 2, 3: 4} In [18]: c.__dict__
Out[18]:
{'_current_app': <object at 0x1597d08>,
'autoescape': True,
'dicts': [{'False': False, 'None': None, 'True': True},
{'d': {1: 2, 3: 4}, 'menu': 'menus', 'page': 'welcome'},
{1: 2, 3: 4}],
'render_context': [{'False': False, 'None': None, 'True': True}],
'template': None,
'template_name': 'unknown',
'use_l10n': None,
'use_tz': None} In [19]: c[1]
Out[19]: 2

django 模板context的理解的更多相关文章

  1. Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)

    前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 ...

  2. django——模板层

    每一个Web框架都需要一种很便利的方法用于动态生成HTML页面. 最常见的做法是使用模板. 模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了,模板层就是 ...

  3. django模板(template)

    模板层(template) 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. 1 2 3 4 def current_datetime ...

  4. [django]模板template原理

    django 中的render和render_to_response()和locals(): http://www.cnblogs.com/wangchaowei/p/6750512.html 什么是 ...

  5. Django模板语言(常用语法规则)

    Django模板语言 The Django template language 模板中常用的语法规则 {最新版本的Django语法可能有改变,不支持的操作可能支持了.[HTML教程 - 基本元素/标签 ...

  6. Django模板层之templates

    一 模版简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now ...

  7. Django——如何在Django模板中注入全局变量?——part1

    问题:TEMPLATE_CONTEXT_PROCESSORS代表着什么? 问题描述:无法在项目的settings.py文件中找到TEMPLATE_CONTEXT_PROCESSORS. ——————— ...

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

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

  9. Django模板常用语法规则

    Django 模板标签 if/else 标签 for 标签 ifequal/ifnotequal 标签 注释标签 过滤器 include 标签 URL标签 模板继承   if/else 标签 1. 基 ...

随机推荐

  1. Python3 读、写Excel文件

    首先,简单介绍一下EXECL中工作簿和工作表的区别: 工作簿的英文是BOOK(WORKBOOK),工作表的英文是SHEET(WORKSHEET). 一个工作簿就是一个独立的文件 一个工作簿里面可以有1 ...

  2. 峰Redis学习(10)Redis 集群(单机多节点集群和多机多节点集群)

    单机多节点集群:参考博客:http://blog.java1234.com/blog/articles/326.html 多机多节点集群:参考博客:http://blog.java1234.com/b ...

  3. Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法

    ylbtech-Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法 1.返回顶部 1. Java 实例 - break 关键字用法  Java 实例 Ja ...

  4. jQuery绑定和解绑点击事件及重复绑定解决办法

    原文地址:http://www.111cn.net/wy/jquery/47597.htm 绑点击事件这个是jquery一个常用的功能,如click,unbind等等这些事件绑定事情,但还有很多朋友不 ...

  5. HTML和SEO基础知识:H标签全透视

    原文地址:http://www.chinaz.com/web/2010/0921/134391.shtml 什么是H标签? h1,h2,h3,h4,h5,h6,作为标题标签,并且依据重要性递减.我认为 ...

  6. Zabbix 课程大纲

    Zabbix 课程笔记  day1 Zabbix 安装  day1 Zabbix 添加主机 day1 Zabbix 创建监控项目 day1 Zabbix 创建触发器 day1 Zabbix 告警内容配 ...

  7. 安装部署Jenkins服务

    1.导入安装包 2.安装安装包 (1).安装JDK和maven 创建jdk存储目录 # mkdir /usr/jdk64/ 解压jdk到存储目录 # tar -zxvf jdk-8u191-linux ...

  8. 为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容

    在开发时,会遇到是要HTML来做UI,是要js与C++进行交互. 在加载完页面后,一些电脑中会出现“为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容”(用IE打开,自 ...

  9. git知识讲解

    git初始化 1.设置名字和邮箱 git config --global user.name "zhangsan" git config --global user.email & ...

  10. vue 非父子组件传值

    /*非父子组件传值 1.新建一个js文件 然后引入vue 实例化vue 最后暴露这个实例 2.在要广播的地方引入刚才定义的实例 3.通过 VueEmit.$emit('名称','数据') 4.在接收收 ...