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. 基 ...
随机推荐
- 黄聪:wordpress如何携带cookie模拟浏览器访问网站
$args = array( 'user-agent' => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, li ...
- Java连接S3并上传Redis
package com.shinho.bigdatalake.redis; import com.amazonaws.regions.Region; import com.amazonaws.regi ...
- 【Graphite学习】系列学习文章-【转】
Graphite 系列 #2:Carbon 和 Whisper GRAPHITE SERIES #1: PROVISION HARDWARE GRAPHITE SERIES #2: CARBON &a ...
- P1507 NASA的食物计划
传送 01背包又进化了,它变成了二维背包. 既然它多了一个维度,那么我们的f[j]也变成了二维数组f[i][j],其中i表示费用1,j表示费用2 核心方程也相应的变成了f[i][j]=max(f[i- ...
- 禅道在docker上部署与迁移
一.禅道部署 1.下载地址 禅道开源版: http://dl.cnezsoft.com/zentao/docker/docker_zentao.zip 数据库用户名: root,默认密码: 123 ...
- python面向对象 : 反射和内置方法
一. 反射 1. isinstance()和issubclass() isinstance( 对象名, 类名) : 判断对象所属关系,包括父类 (注:type(对象名) is 类名 : 判断对象所属 ...
- [UE4]关卡蓝图
- hook mono实现Assembly.Load从指定路径读取文件
mono-unity github: https://github.com/Unity-Technologies/mono/blob/unity-staging/mono/metadata/assem ...
- jquery选择器筛选器
jQuery对象 Query 对象就是通过jQuery包装DOM对象后产生的对象.jQuery 对象是 jQuery 独有的. 如果一个对象是 jQuery 对象, 那么它就可以使用 jQuery 里 ...
- Java 13 - Java 数组
Java 数组 数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同. Java语言中提供的数组是用来存储固定大小的同类型元素. 你可以声明一个数组变量,如num ...