Django 使用 locals()

7 投票
4 回答
12561 浏览
提问于 2025-04-18 15:31

我刚开始学习用Django做网页开发。我发现这里用的是locals()这个函数,而不是我习惯看到的上下文字典。

从网上的信息来看,locals()挺有用的,那有没有什么特殊情况是它不太适合,反而用context_dictionary更好呢?

4 个回答

0

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() 可能是个好主意。

0

你说的上下文字典是指命名参数吗?如果是的话,它们是不同的。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}}

2

如果你的视图看起来像这样:

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)
17

在那个教程中使用 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>

你将会得到预期的结果。

撰写回答