Django - 从自定义过滤器中访问RequestContext

Dom*_*ger 14 python django django-templates

我有一个过滤器currency,它取一个美元的价值并将其转换为一种货币(美元或英镑).要转换的货币存储在会话中,但过滤器不会占用RequestContext,所以我无法从那里直接获取它.

有没有比将相关会话元素传递到模板更好的方法,以及从模板到过滤器作为参数?虽然这种方法有效,但似乎相当可怕,而且我很可能最终将货币传递给(几乎)每个模板.

我的过滤器目前看起来像这样:

def currency(value, currency):
    if currency == 'usd':
       val = '$%.2f' % value
       return mark_safe(val)

    d = Decimal(value)
    val = '£%.2f' % (d*Decimal('0.63'))

    return mark_safe(val)
Run Code Online (Sandbox Code Playgroud)

Ada*_*dam 7

如果您创建模板标记而不是过滤器,则会为您提供要使用的上下文(包含请求). http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags


Dan*_*den 7

我不得不同意 Adam 的观点,将代码迁移到自定义标记是最好的方法。

但是,只有在发布页面并且拥有大量使用现有过滤器语法的模板时,客户端才需要记录某些过滤器的使用。重写所有模板将是一项代价高昂的工作。所以,我想出了这个从调用堆栈中提取上下文的简单函数:

https://gist.github.com/drhoden/e05292e52fd5fc92cc3b

def get_context(max_depth=4):
    import inspect
    stack = inspect.stack()[2:max_depth]
    context = {}
    for frame_info in stack:
        frame = frame_info[0]
        arg_info = inspect.getargvalues(frame)
        if 'context' in arg_info.locals:
            context = arg_info.locals['context']
            break
    return context
Run Code Online (Sandbox Code Playgroud)

请务必阅读我的警告,但这确实允许标准过滤器访问上下文(如果可用),而无需将过滤器转换为标签。

  • 太棒了,不确定是好是坏,但是太棒了 ;) (4认同)
  • 我既印象极其深刻,又感到极其震惊。出色的。:D (3认同)

Zac*_*ach 5

这可以使用过滤器来完成。首先确保你"django.core.context_processors.request"TEMPLATE_CONTEXT_PROCESSORS。如果不这样做,您可以将其添加到您的 settings.py 文件中:

TEMPLATE_CONTEXT_PROCESSORS += (
    "django.core.context_processors.request"
)
Run Code Online (Sandbox Code Playgroud)

然后在您的模板中,您的过滤器将如下所示(假设您的会话变量名为“currency_type”):

{{value|currency:request.session.currency_type}}
Run Code Online (Sandbox Code Playgroud)

或者您认为这样的事情相当可怕?