Django模板和当地人的把戏

django书籍给出了当地的把戏,以避免键入一长串的参数作为上下文词典http://www.djangobook.com/en/2.0/chapter04/

它向懒惰的程序员推荐这一点,但指出可能会影响性能的一些开销。

我想知道你们中的一些人是否在真实应用程序中使用当地人的技巧。 你推荐它还是一个不好的做法?

我不喜欢重复 – 我认为“干”,“不要重复自己”,是一个关键的编程原则。 因此,我确实在类似的情况下使用了locals() 。 Django模板渲染远不是这种唯一的情况:一般情况是“接受字典的函数或运算符,但不介意字典是否包含额外的条目”。 (例如,Python中的普通string格式是另一种情况)。

然而,有一个反补贴的原则:程序应该可以用本地化的方式来理解 – 这有助于维护和重构(因为它避免了研究其他文件来检查什么是重构是可以接受的)。 这表明,对于locals()情况下,如果模板(或string格式等)是一个本地文字(less数variables可能被使用,因此locals()是不是一个巨大的胜利的罕见情况! – ),但在模板位于不同文件的正常情况下会出现问题。

因此,在大多数情况下,使用locals() ,严重阻碍重构。 几乎在Python的每一种情况下,局部variables及其名称都可以作为局部重构的一部分自由地改变,因为它们没有“外部可见的”效果……但是使用局部variableslocals()打破了这个效果 -将variables重命名为不同的名称,提供更好的清晰度,以不需要variables等的方式重构代码stream,而不必每次都研究单独的模板文件以检查是否可能不需要旧名称并可能编辑模板文件,这可能是不平凡的,例如,如果为了i18n / L10n的目的而以几种不同的自然语言维护)。

因此,除了性能问题的第二个问题之外,在“严重”,“生产”代码使用locals()需要长期维护,因此易于重构和本地化,这是强大的压力。 所以,当我“尽我所能地编程,我知道如何”,而不是“偷工减料”,我知道我最好避免locals()

毕竟,你想在渲染模板的上下文中使用的值不一定是“自然”可用的, 也许其中一些或许多是计算结果,来自列表或词典的项目等等。 在这种情况下,如果您只是将这些值累加到合适的字典中,而不是将它们分配给本地裸机名称, locals()容易避免使用locals()进行“切angular”的诱惑。

这不是最容易的折衷,因为两个好的原则(避免重复,并具有良好的局部性)不可避免地会发生冲突 – 因此,这是一个很好的问题! 而不是完全容易受到尖锐的黑色或白色的答案,这就是为什么我试图扩大双方。 最后,我认为这是一个“风格”的方面,编程团队可能会被build议采用团队统一的风格指导方针并坚持下去 – 至less不需要每次都做出决定这个问题就出现了,并且产生了一个更加均匀(因此可维护)的代码库。 [[我必须承认,这个具体的观点从来没有在我参加过的球队的风格指导中得到明确的解决,虽然其他很多球队也有!]]]

我经常想到做下面的事情,但我不确定是否真的有帮助。

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

我个人不喜欢。 对于我的偏好,可能没有任何理由,除了旧的Python的格言“显式优于隐式”。 我想知道到底是什么进入我的模板。

我已经使用它没有任何问题(到目前为止!)。

我不喜欢打字,这就是为什么我喜欢它。 代码如

 'customer' : customer, 'invoice' : invoice, 'date' : date 

只是看起来很可笑,如果我能避免它,我会的。 我喜欢Python的原因之一是缺乏样板(虽然这不是真正的样板,但它是相似的)。

我想这取决于你在函数中定义了多less个局部variables。

如果它匹配你想要的数字返回到你的模板,或者“额外”variables是简单的结构,如整数或布尔值,那么我想没有必要明确地返回它们,因为这需要更多的工作。

但是另一方面,如果你的视图有很多复杂的“帮助”variables,比如你在视图中使用的模型实例来生成你想发送给模板的数据,那么你可能要考虑使用显式的variables返回到模板。

我同意亚历克斯。 当你可以这样做的时候,没有看到创build一个类实例(像nielsbuild议的那样):

 def my_view(request, id): customer = .. invoice = .. date = .. return render_to_response('xxx,html', locals()) 

如果您需要性能原因,虚线查找速度较慢。

如果你想维护的原因,这是更less的代码行, 可读,更less的不必要的结构。

我知道这是一个旧线程…目前render_to_response已弃用。 使用渲染而不使用本地()。 绕过所有当地人是不好的做法。 这里是一个views.py的例子:

 from django.shortcuts import render from django.contrib.auth.decorators import login_required @login_required def mybooks(request): entries = Book.objects.all() return render(request, 'mybooks.html', {'entries': entries}) 

这个解决scheme减less了views.py混乱,同时保持事物的明确性。

controllers.py

 import sys def auto_context(the_locals=None): # Take any variable in the locals() whose name ends with an underscore, and # put it in a dictionary with the underscore removed. if the_locals is None: # We can access the locals of the caller function even if they # aren't passed in. caller = sys._getframe(1) the_locals = caller.f_locals return dict([ (key[:-1], value) for (key, value) in the_locals.items() if key[-1] == "_"]) 

views.py

 # import the above controller def a_view(request): a_string_ = "Hello" # This'll go into the context. another_string = "World" # This won't. # Add local variables ending in an underscore to context return render(request, "template.html", auto_context()) 

template.html ,使用{{ a_string }}

你不太可能给一个variables名称以一个下划线结尾。 所以你会知道到底是什么进入模板。 使用auto_context(locals())auto_context()也可以。