2009-09-29 50 views
14

我有一個過濾器currency,它以美元價值並將其轉換爲貨幣(美元或英鎊)。要轉換的貨幣存儲在會話中,但過濾器不需要RequestContext,所以我無法從中直接獲取它。Django - 從自定義過濾器中訪問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) 

回答

7

,您將得到與工作(其中包含請求)的情況下。 http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

+1

@亞當 - 也許我很厚,但我不能在那些文檔中看到如何從自定義模板標籤中訪問會話變量。你能否給我一個例子或指出我錯過了什麼? –

+1

啊 - 挖掘它似乎是作爲第一個參數傳遞給標籤(剛剛找到一個例子,它添加了一個類與鏈接匹配正則表達式,看起來(一)有用和(二)適應性 - http:// gnuvince .wordpress.com/2007/09/14/A-Django的模板標籤換了,目前活躍的頁/)。 –

+0

對,上下文是模板標籤節點上渲染方法的標準參數。如果你需要一個更具體的例子,我相信我可以鼓起一個。 – Adam

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}} 

或者是這樣的東西你正在考慮相當可怕嗎?

+0

他是;看看他在做什麼,該過濾器正確地描述了你所說的內容。 – fijter

+0

我想他可能會抱怨必須通過視圖顯式傳遞變量的過程。這將使其自動可用。我也可以發佈一個在decorator中使用帶有takes_context = True的模板標籤的例子 – Zach

3

我不得不同意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 

請務必仔細閱讀我的警告,但這並給予標準過濾器訪問上下文(當它可用)而不必將您的過濾器變成標籤。

+1

這很棒,不知道是好的還是壞的方式,但真棒;) –

0

丹尼爾羅登的建議是一種不太方便的解決方案,使用threading.local()。定義一箇中間件類,它將request作爲全局對象存儲在本地線程中,然後將該類添加到MIDDLEWARE_CLASSES

現在模板過濾器可以輕鬆訪問該請求對象。