python Django - 从自定义过滤器中访问 RequestContext
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1493874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Django - accessing the RequestContext from within a custom filter
提问by Dominic Rodger
I've got a filter currency
, which takes a value in USD and converts it to a currency (either USD or GBP). The currency to convert to is stored in the session, but filters don't take RequestContext
, so I can't grab it straight from there.
我有一个 filter currency
,它以美元为单位取值并将其转换为货币(美元或英镑)。要转换为的货币存储在会话中,但过滤器不接受RequestContext
,因此我无法直接从那里获取它。
Is there a better way than passing the relevant session element into the template, and from the template into the filter as an argument? Whilst this approach is working, it seems fairly horrible, and I'm likely to end up passing the currency to (almost) every template.
有没有比将相关会话元素传递到模板中,并从模板中作为参数传递到过滤器中更好的方法?虽然这种方法有效,但它似乎相当可怕,而且我可能最终将货币传递给(几乎)每个模板。
My filter currently looks something like this:
我的过滤器目前看起来像这样:
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)
采纳答案by Adam
If you create a template tag instead of a filter, you are given the context to work with (which contains the request). http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
如果您创建模板标记而不是过滤器,则会为您提供要使用的上下文(其中包含请求)。 http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags
回答by Daniel Rhoden
I would have to agree with Adam that migrating the code to a custom tag is the best way.
我不得不同意 Adam 的观点,即将代码迁移到自定义标记是最好的方法。
However, a client needed to record the use of certain filters only when a page was published and had a HUGE inventory of templates that used the existing filter syntax. It would have been a costly undertaking to rewrite all the templates. So, I came up with this simple function that extracts the context from the call stack:
但是,只有在发布页面并且拥有大量使用现有过滤器语法的模板时,客户端才需要记录某些过滤器的使用。重写所有模板将是一项代价高昂的工作。所以,我想出了这个从调用堆栈中提取上下文的简单函数:
https://gist.github.com/drhoden/e05292e52fd5fc92cc3b
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
Be sure to read my warnings, but this DOES give standard filters access to the context (when it is available) WITHOUT having to turn your filter into a tag.
请务必阅读我的警告,但这确实允许标准过滤器访问上下文(当它可用时),而不必将过滤器转换为标签。
回答by Zach
This can be done using a filter. First make sure that you have "django.core.context_processors.request"
in you TEMPLATE_CONTEXT_PROCESSORS
. If you don't, you can add this to your settings.py file:
这可以使用过滤器来完成。首先确保你有"django.core.context_processors.request"
你TEMPLATE_CONTEXT_PROCESSORS
。如果不这样做,您可以将其添加到 settings.py 文件中:
TEMPLATE_CONTEXT_PROCESSORS += (
"django.core.context_processors.request"
)
Then in your template, your filter will look like this (assuming your session variable is named 'currency_type'):
然后在您的模板中,您的过滤器将如下所示(假设您的会话变量名为“currency_type”):
{{value|currency:request.session.currency_type}}
Or is something like this what you are considering fairly horrible?
或者像这样的事情你认为相当可怕?
回答by jrief
A somehow less hacky solution to Daniel Rhoden's proposal is, to use threading.local()
. Define a middleware class, which stores your request
as a global object inside your local thread, and add that class to your MIDDLEWARE_CLASSES
.
对于 Daniel Rhoden 的提议,一个不那么笨拙的解决方案是使用threading.local()
. 定义一个中间件类,它将您request
作为全局对象存储在您的本地线程中,并将该类添加到您的MIDDLEWARE_CLASSES
.
Now a template filter can easily access that request object.
现在模板过滤器可以轻松访问该请求对象。