Django 使用 locals()
我刚开始学习用Django做网页开发。我发现这里用的是locals()
这个函数,而不是我习惯看到的上下文字典。
从网上的信息来看,locals()
挺有用的,那有没有什么特殊情况是它不太适合,反而用context_dictionary
更好呢?
4 个回答
locals()
是一个 Python 内置函数,根据官方 Python 文档的说明:
它会更新并返回一个字典,表示当前的本地符号表。当在函数块中调用
locals()
时,会返回自由变量,但在类块中则不会。
举个例子:
In [1]: def f():
...: a = 1
...: b = 2
...: c = 'three'
...:
...: return locals()
...:
In [2]: f()
Out[2]: {'a': 1, 'b': 2, 'c': 'three'}
我觉得 locals()
可能会很有用,特别是当你想创建一个包含你在视图中定义的变量的字典时(通常你创建的大部分或全部变量都会包含在上下文字典中)。
不过,使用 locals()
并不利于重构。在重构时,视图中的局部变量可能会随意改变。这样一来,你就不能安全地重命名一个变量,因为它们不会有明显的效果。你可能还会遇到另一个问题,那就是 性能,因为你可能会把一些其实并不需要的变量也包含在上下文中。如果你的视图声明了很多临时变量,可能会导致上下文过载。
因此,避免使用 locals()
可能是个好主意。
你说的上下文字典是指命名参数吗?如果是的话,它们是不同的。locals会显示所有的局部变量,而kwargs字典只显示命名参数。
def test(**kwargs):
c = 'abc'
print kwargs
print locals()
test(a=10, b=20)
第一个打印出来的是:{'a': 10, 'b': 20},而第二个打印出来的是:{'c': 'abc', 'kwargs': {'a': 10, 'b': 20}}
如果你的视图看起来像这样:
def myview(request):
thing = 1
name = 'fred'
stuff = ['a', 'b', 'c']
而在你的模板中你想做:
{{ thing }} of {{ name }} has {% for x in stuff %}{{ x }}{% endfor %}
那么在视图中你可以这样做:
return render(request, 'template.html', locals())
这是因为 locals()
会返回一个字典,里面包含了当前作用域内所有定义的变量。所以这算是一种比较隐蔽的快捷方式。
不过要小心,因为这样可能会暴露出比你想要的更多的值……一般来说,我们更倾向于遵循“明确比隐含更好”的原则,来自 Python之禅,也就是说,最好定义一个字典,只包含你想传递给模板的内容。
def myview(request):
context = {
'thing': 1,
'name': 'fred',
}
# do more code...
context['stuff'] = ['a', 'b', 'c']
return render(request, 'template.html', context)
在那个教程中使用 locals()
只是为了方便,因为他需要传递给模板的数据都存储在本地变量里。 locals()
会返回一个字典,这个字典里包含了本地变量的名字(作为键)和当前的值(作为值)。
如果你需要自己构建数据,而这些数据没有存放在单独的变量里,那么就需要使用一个明确的上下文字典,而不是直接传 locals()
。
locals()
和上下文字典都是字典类型的对象,这就是唯一的要求:你需要一个像字典一样的对象(也就是说,它需要支持 __getitem__(key)
和 get(key, default=None)
这两个方法)。你获取这个字典的方式可以由你自己决定。没有固定的做法,但可以选择以下几种方式:
- 如果你使用
CONTEXT_PROCESSORS
,可以返回一个RequestContext()
,它是一个类似字典的对象。 - 如果你的数据在本地变量中,可以返回
locals()
。 - 否则,可以手动创建一个字典来存放你的数据。
编辑 - 示例:
自己构建字典的示例:
def my_view(request):
return render_to_response('hello.html', {
'full_name': u"%s %s" % (request.user.first_name, request.user.last_name),
'username': request.user.username
})
从 locals()
构建字典的示例:
def my_view(request):
full_name = u"%s %s" % (request.user.first_name, request.user.last_name)
username = request.user.username
return render_to_response('hello.html', locals())
假设 hello.html 在这两种情况下都是:
<html>
<body>
You are {{ full_name }} ({{ username }})
</body>
</html>
你将会得到预期的结果。