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. Python单元测试框架之pytest 1 ---如何执行测试用例

    From: https://www.cnblogs.com/fnng/p/4765112.html 介绍   pytest是一个成熟的全功能的Python测试工具,可以帮助你写出更好的程序. 适合从简 ...

  2. 【C#】C#操作Excel文件(转)

    实现C#与Excel文件的交互操作,实现以下功能: 1.DataTable 导出到 Excel文件 2.Model数据实体导出到 Excel文件[List<Model>] 3.导出数据到模 ...

  3. 堆叠箱子(基础dp)

    P1086 时间限制: 1 Sec  内存限制: 128 MB提交: 38  解决: 27[提交][状态][讨论版][命题人:外部导入] 题目描述 现有N种箱子,每种箱子高度H_i,数量C_i.现选取 ...

  4. 字符串全部转换为大写用str.toUpperCase()方法

    var message="Hello world!"; var x=message.toUpperCase();

  5. [转][easyui]右键菜单

    来自:Zephyr.Net开发手册 var $tab = $('#tabs'); var currentTab = $tab.tabs('getSelected'); var titles = wra ...

  6. [转][html]设置IIS 默认页

    <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.we ...

  7. 总结查看端口、进程占用情况(lsof、netstat、ps、kill)

    一.Linux查看端口占用情况 1.lsof(list open files)列出当前系统打开文件 查看指定端口号语法格式: lsof -i:端口号 如果命令找不到 [root@bogon ~]# l ...

  8. echart力导向图

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="GBK" ...

  9. U3D学习004——核心类和代码运行

    1.U3D核心类 2.变量 只有public变量才可以显示在inspector面板中,[serializeField]可以使private和protected变量显示在inspector面板中. 3. ...

  10. Python的多态、继承与封装

    一.多态 不用知道变量所引用的对象类型,还是能对它进行操作,它会根据对象(或类)的类型不同而表现出不同的行为. def run_twice(animal): animal.run() animal.r ...