代码之家  ›  专栏  ›  技术社区  ›  Dominic Rodger

django-从自定义筛选器中访问requestContext

  •  14
  • Dominic Rodger  · 技术社区  · 15 年前

    我有个过滤器 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)
    
    4 回复  |  直到 8 年前
        1
  •  7
  •   Adam    15 年前

    如果您创建了一个模板标记而不是一个过滤器,您将得到要使用的上下文(其中包含请求)。 http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

        2
  •  4
  •   Daniel Rhoden    9 年前

    我必须同意亚当的观点,即将代码迁移到自定义标记是最好的方法。

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

    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
    

    一定要阅读我的警告,但这确实使标准过滤器可以访问上下文(当上下文可用时),而不必将过滤器转换为标记。

        3
  •  3
  •   Zach    15 年前

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

    TEMPLATE_CONTEXT_PROCESSORS += (
        "django.core.context_processors.request"
    )
    

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

    {{value|currency:request.session.currency_type}}
    

    或者像这样的事情是你认为相当可怕的吗?

        4
  •  0
  •   jrief    9 年前

    丹尼尔·罗登提议的一个不那么老套的解决方案是 threading.local() . 定义一个中间件类,它存储 request 作为本地线程中的全局对象,并将该类添加到 MIDDLEWARE_CLASSES .

    现在,模板过滤器可以轻松地访问该请求对象。