django:用较少的仪式定义标签/过滤器/经理行动

时间:2014-03-21 21:36:53

标签: python django django-1.7

要创建自定义django模板标记和过滤器,以及添加自定义manage.py命令,无论多么微不足道,文档都会告诉您创建特定的目录结构。

我正在开展一个非常小的项目,我很难将应用程序的结构复杂性加倍,只是为了添加一个小小的过滤器或命令。

有没有办法以紧凑,直接的方式注册标签,过滤器和命令?在我想要的任何地方势不可挡,而不是在目录层次结构中以声明的方式2级?

1 个答案:

答案 0 :(得分:0)

虽然有点hackish,但事实证明标签/过滤器的情况完全可能。命令,否:django实际上在文件系统中搜索所涉及的.py文件。

模板hack是完全独立的 - 它不会将可疑的东西泄漏到附近的代码中。单个模块可以容纳所有的metamagic,并由常规模块导入。

首先,我们必须创建一个模拟模块。我们将创建一个很好的装饰器来将常规类转换为模块:

def module(path):
    def decorator(cls):
        if '.' in path:
            parent_path, name = path.rsplit('.', 1)
            module(parent_path)(type(name, (object,), { name: cls }))

        return sys.modules.setdefault(path, cls)
    return decorator

是的,递归是必要的(我们需要模拟完整的导入路径),它可以用来创建一个假的templatetags模块,如下所示:

@module('app.templatetags.extras')
class TemplateExtras(object):
    class register:
        tags    = {}
        filters = {}

# Optional: avoid using {% load %}:
django.template.libraries['app.templatetags.extras'] = TemplateExtras
django.template.base.add_to_builtins('app.templatetags.extras')

在混合中添加两个漂亮的装饰器......

def templatetag(f):
    return TemplateExtras.register.tags.setdefault(f.__name__, f)

def templatefilter(f):
    return TemplateExtras.register.filters.setdefault(f.__name__, f)

...您将获得以下干净,直接的语法:

# imported or present in app/__init__.py
@templatefilter
def datestr(date):
    return datetime.strftime(date, '%Y-%m-%d')