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. windows安装mysql数据库并修改密码

    1.下载 MySQL Community Server https://dev.mysql.com/downloads/mysql/ 2.解压 如果想要让MySQL安装在指定目录,那么就将解压后的文件 ...

  2. 【java】之类加载机制

    类加载: 类加载机制是指.class文件加载到jvm,并形成Class对象的机制,之后的应用就可对Class对象进行实例化并调用,类加载机制可在运行时动态加载外部的类,远程网络下载过来的class文件 ...

  3. python接口自动化20-requests获取响应时间(elapsed)与超时(timeout) ok试了 获取响应时间的

    前言 requests发请求时,接口的响应时间,也是我们需要关注的一个点,如果响应时间太长,也是不合理的.如果服务端没及时响应,也不能一直等着,可以设置一个timeout超时的时间 关于request ...

  4. Web jsp开发学习——实现页面跳转和传参

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcepti ...

  5. ubuntu 间简单相互通信

    1.  nc  命令 在一台机器上运行nc -l 来监听本机的2222号端口 另外一台机器就能连接到这台监听的机器上,假设上面那台机器的ip是192. nc 之后就能互相发送字符了 2. iptux通 ...

  6. Redis禁用持久化功能的设置

    原文转载至:https://www.cnblogs.com/rangeon/p/7067618.html 用过Redis的朋友都知道,这玩意有个比较强大的功能叫做持久化,就是在结束服务的时候把缓存中的 ...

  7. Android 设置SeekBar不可拖动

    public class MyProgressBar extends SeekBar { /** * 是否支持拖动进度 */ private boolean touch = true; public ...

  8. UE4中多种颜色轮廓线的后期处理

    转自:http://blog.csdn.net/pizi0475/article/details/50396277 随着近来虚幻引擎4的一些变化,渲染多种颜色的轮廓线已经可以实现了!通过自定义模板,类 ...

  9. [电脑知识点]win10家庭版怎么显示桌面图标

    控制面板-------->外观和个性化-------->个性化-------->更改桌面图标-------->然后你就能看到你想要的东西了,勾选上就可以了

  10. Delphi根据方法名调用方法

    type   TForm1 = class(TForm) public published     procedure DoJsCall(str:string);                   ...