django 模板context的理解
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的理解的更多相关文章
- Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)
前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 ...
- django——模板层
每一个Web框架都需要一种很便利的方法用于动态生成HTML页面. 最常见的做法是使用模板. 模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了,模板层就是 ...
- django模板(template)
模板层(template) 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. 1 2 3 4 def current_datetime ...
- [django]模板template原理
django 中的render和render_to_response()和locals(): http://www.cnblogs.com/wangchaowei/p/6750512.html 什么是 ...
- Django模板语言(常用语法规则)
Django模板语言 The Django template language 模板中常用的语法规则 {最新版本的Django语法可能有改变,不支持的操作可能支持了.[HTML教程 - 基本元素/标签 ...
- Django模板层之templates
一 模版简介 你可能已经注意到我们在例子视图中返回文本的方式有点特别. 也就是说,HTML被直接硬编码在 Python代码之中. def current_datetime(request): now ...
- Django——如何在Django模板中注入全局变量?——part1
问题:TEMPLATE_CONTEXT_PROCESSORS代表着什么? 问题描述:无法在项目的settings.py文件中找到TEMPLATE_CONTEXT_PROCESSORS. ——————— ...
- Django模板语言,标签整理
Django模板语言 标签 内置标签引用 1. autoescape 控制自动转义是否可用. 这种标签带有任何 on 或 off 作为参数的话,他将决定转义块内效果. 该标签会以一个endautoes ...
- Django模板常用语法规则
Django 模板标签 if/else 标签 for 标签 ifequal/ifnotequal 标签 注释标签 过滤器 include 标签 URL标签 模板继承 if/else 标签 1. 基 ...
随机推荐
- Python3 读、写Excel文件
首先,简单介绍一下EXECL中工作簿和工作表的区别: 工作簿的英文是BOOK(WORKBOOK),工作表的英文是SHEET(WORKSHEET). 一个工作簿就是一个独立的文件 一个工作簿里面可以有1 ...
- 峰Redis学习(10)Redis 集群(单机多节点集群和多机多节点集群)
单机多节点集群:参考博客:http://blog.java1234.com/blog/articles/326.html 多机多节点集群:参考博客:http://blog.java1234.com/b ...
- Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法
ylbtech-Java-Runoob-高级教程-实例-方法:08. Java 实例 – break 关键字用法 1.返回顶部 1. Java 实例 - break 关键字用法 Java 实例 Ja ...
- jQuery绑定和解绑点击事件及重复绑定解决办法
原文地址:http://www.111cn.net/wy/jquery/47597.htm 绑点击事件这个是jquery一个常用的功能,如click,unbind等等这些事件绑定事情,但还有很多朋友不 ...
- HTML和SEO基础知识:H标签全透视
原文地址:http://www.chinaz.com/web/2010/0921/134391.shtml 什么是H标签? h1,h2,h3,h4,h5,h6,作为标题标签,并且依据重要性递减.我认为 ...
- Zabbix 课程大纲
Zabbix 课程笔记 day1 Zabbix 安装 day1 Zabbix 添加主机 day1 Zabbix 创建监控项目 day1 Zabbix 创建触发器 day1 Zabbix 告警内容配 ...
- 安装部署Jenkins服务
1.导入安装包 2.安装安装包 (1).安装JDK和maven 创建jdk存储目录 # mkdir /usr/jdk64/ 解压jdk到存储目录 # tar -zxvf jdk-8u191-linux ...
- 为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容
在开发时,会遇到是要HTML来做UI,是要js与C++进行交互. 在加载完页面后,一些电脑中会出现“为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容”(用IE打开,自 ...
- git知识讲解
git初始化 1.设置名字和邮箱 git config --global user.name "zhangsan" git config --global user.email & ...
- vue 非父子组件传值
/*非父子组件传值 1.新建一个js文件 然后引入vue 实例化vue 最后暴露这个实例 2.在要广播的地方引入刚才定义的实例 3.通过 VueEmit.$emit('名称','数据') 4.在接收收 ...