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 Ajax 403 仅在从自定义 localhost url 发布时