Django 模板和 locals 技巧
这本django书里介绍了一种本地技巧,可以避免输入一长串参数作为上下文字典。
http://www.djangobook.com/en/2.0/chapter04/
举个例子:
def current_datetime(request):
dt_now = datetime.datetime.now()
return render_to_response('current.html', {'dt_now': dt_now})
变成:
def current_datetime(request):
dt_now = datetime.datetime.now()
return render_to_response('current.html', locals())
这招是为了懒程序员推荐的,但也提到了一些额外的开销,可能会影响性能。
我想知道你们中有没有人在实际应用中使用这个本地技巧。你们觉得推荐吗,还是说这是个坏习惯?
8 个回答
我个人不太喜欢这样做。可能没有特别的理由,只是因为老话说的“显式比隐式好”。我喜欢清楚地知道我的模板里到底放了什么。
我经常想要做以下事情,但我不太确定这样做是否真的有帮助。
class MyStruct(object):
pass
def my_view(request, id):
c = MyStruct()
c.customer = ..
c.invoice = ..
c.date = ..
return render_to_response('xxx,html',c.__dict__)
我不喜欢重复的事情——我觉得“DRY”,也就是“不要重复自己”,是编程中的一个重要原则。因此,在类似的情况下,我确实使用过locals()
。不过,Django模板渲染并不是唯一的这种情况:一般来说,就是“一个函数或操作符可以接受一个字典,但不介意字典里有多余的条目”。(比如,Python中的普通字符串格式化也是这样的情况。)
但是,还有一个相对的原则:程序应该尽可能容易理解——这有助于维护和重构(因为这样就不需要去研究其他文件,看看哪些重构是可以接受的)。这就意味着,在使用locals()
的情况下,如果模板(或者字符串格式等)是一个本地的字面量(这种情况比较少见,通常只有少数变量被使用,因此locals()
的优势不大!),那是可以的,但如果模板在不同的文件里,就会有问题。
因此,在大多数情况下,使用locals()
会严重妨碍重构。在Python的几乎所有情况下,局部变量及其名称可以自由更改,因为它们没有“外部可见”的影响……但使用locals()
就打破了这一点——突然之间,你不能安全地将一个变量重命名为更清晰的名称,也不能以一种去掉变量的方式重构代码流等等,而每次都需要查看一个单独的模板文件,确认旧名称是否还需要(而且可能还需要编辑模板文件,这可能并不简单,比如如果它是为了国际化/本地化而维护的多种语言版本)。
因此,除了性能的次要问题外,在“严肃的”、“生产级”的代码中,强烈不建议使用locals()
——这种代码需要长期维护,因此需要容易重构和良好的局部性。所以,当我“尽我所能地编程”而不是“偷工减料”时,我意识到我最好避免使用locals()
。
你希望在渲染模板的上下文中使用的值,并不一定“自然”地以局部名称的形式存在;也许其中一些或许很多都是计算的结果,或者是列表或字典中的项目等等。在这种情况下,如果你将这些值累积到一个合适的字典中,而不是给它们分配局部名称,那么避免用locals()
的诱惑就会更容易。
这并不是最简单的权衡,因为两个好的原则(避免重复和保持良好的局部性)不可避免地发生冲突——所以,这是个好问题!而且这个问题并不是完全可以用黑白分明的答案来解决的,这就是我试图扩展两方面的原因。最后,我认为这是一个“风格”方面的问题,编程团队可能会被建议采用统一的团队风格指南并坚持下去——至少这样就不需要每次出现这个问题时都做出决定,从而产生一个更统一(也更易维护)的代码库。[[我必须承认,这个具体的点在我参与的团队的风格指南中从未被明确提及过,尽管其他许多方面都有!-)]]