比locals()或dict(foo = foo)更好的东西,用于将上下文导出到模板引擎

时间:2013-02-21 23:08:35

标签: python django jinja2

所以,在对#python关于why not to use locals的简短讨论之后,我正在思考如果没有dict(foo=foo,bar=bar)的重复性质(即不是DRY)会有什么更好的方式(或者使用文字语法({}))。

理想情况下,可以提交镜像this ecmascript harmony proposal的PEP(或已经存在的PEP)。 (我想强调它传达的DRY方面)。

那么,你有什么解决方案吗?我应该提交PEP吗?

3 个答案:

答案 0 :(得分:0)

我目前提出的解决方案是以下模式。请告诉我这是否与使用locals()一样糟糕。

class _Context:
    foo = 'bar'
render(request, 'example.html', vars(_Context))

有一点需要注意的是,使用python3可能会有点不确定,因为它会使用带有不可变dictproxy的新式类,我需要看看它如何与给定的模板库进行交互。使用简单的'{foo}'.format(**_Context.__dict__)工作正常。

是对locals()的明显改进,因为它相当明确,并且不泄漏本地范围的其他部分。但是,它确实会泄漏'__module__''__doc__'旧样式类以及其他一些新类型的东西。

答案 1 :(得分:0)

这是我的解决方案。可能有更好的方法来构建它,但它可以工作!

设置(Python 2和3):

class ContextDictBase(type):
    @staticmethod
    def __newnew(cls, name, bases, attrs):
        attrs.pop('__module__', None)
        return attrs
    def __new__(cls, name, bases, attrs):
        ContextDictBase.__new__ = staticmethod(ContextDictBase.__newnew)
        return super(ContextDictBase, cls).__new__(cls, name, bases, attrs)

Python 2:

class ContextDict(object):
    __metaclass__ = ContextDictBase

Python 3:

class ContextDict(object, metaclass=ContextDictBase):
    pass

然后使用它:

class context(ContextDict):
    a = 1
    b = 2

>>> context
{'a': 1, 'b': 2}

答案 2 :(得分:0)

元类/ attrs解决方案的变体:

def make_dict(name, bases, attrs):
    attrs.pop('__module__')
    attrs.pop('__metaclass__', None)  # not needed in python3
    return attrs

Python 2:

class Context:
    __metaclass__ = make_dict

Python 3:

class Context(metaclass=make_dict):
    a = 1
    b = 2

真的,这个问题刚刚变成了我的沙盒,用于播放元类