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

Posted

技术标签:

【中文标题】Django - 从自定义过滤器中访问 RequestContext【英文标题】:Django - accessing the RequestContext from within a custom filter 【发布时间】:2010-12-02 09:46:05 【问题描述】:

我有一个过滤器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)

【问题讨论】:

【参考方案1】:

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

【讨论】:

@Adam - 也许我很厚,但我在那些文档中看不到如何从自定义模板标签中访问会话变量。你能给我一个例子或指出我缺少什么吗? 啊 - 挖掘它似乎是作为标签的第一个参数传递的(刚刚找到一个示例,它将一个类添加到与正则表达式匹配的链接中,它看起来(a)有用并且(b)适应性强 - gnuvince.wordpress.com/2007/09/14/…)。 对,context是模板标签节点上render方法的标准参数。如果您需要更具体的示例,我相信我可以召集一个。 好吧,看看发布的 URL 中的示例,它并不完全相同,因为作者明确传递了请求。如果您将模板标签编写为编译和渲染器方法的混合体,则无需显式地从模板中执行任何操作即可传递上下文。【参考方案2】:

我必须同意 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

请务必阅读我的警告,但这确实使标准过滤器可以访问上下文(当它可用时),而不必将您的过滤器变成标签。

【讨论】:

太棒了,不知道是好是坏,但是太棒了;) 我既感动又害怕。优秀。 :D【参考方案3】:

这可以使用过滤器来完成。首先确保你有"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】:

对于 Daniel Rhoden 的提议,一个不那么老套的解决方案是使用 threading.local()。定义一个中间件类,它将您的request 存储为本地线程中的全局对象,并将该类添加到您的MIDDLEWARE_CLASSES

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

【讨论】:

以上是关于Django - 从自定义过滤器中访问 RequestContext的主要内容,如果未能解决你的问题,请参考以下文章

从自定义 Django 用户模型中删除密码

在 django 模板中过滤 object_list

Django Ajax 403 仅在从自定义 localhost url 发布时

WordPress > 从自定义帖子类型获取自定义分类

如何通过分类术语从自定义 WordPress MySQL 查询中排除结果

从自定义标头中检索访问令牌