2011-08-07 32 views
1

在Django中,在一個模板變量的點理論上表示一個查找,基於分辨率的以下順序上:Django的:模板字典/對象交叉引用

  • 字典查找。示例:foo["bar"]
  • 屬性查找。示例:foo.bar
  • 方法調用。示例:foo.bar()
  • 列表索引查找。示例:foo[bar]

rendering a context in django 1.2(docs.djangoproject.com)。

在現實:

視圖

... 
class Veggie(object): 
    def __init__(self, name): 
     self.name = name 
veggies = {'a': Veggie('carrot'), 'b': Veggie('lettuce')} 

basket = ['a', 'c', 'b'] 

return render_to_response('tpls/veggies.txt', 
     {'veggies': veggies, 'basket': basket}, 
     mimetype="text/plain") 

模板

Veggie by basket order, showing name 

{% for veg in basket %} 
    {{ veg }} 
    {{ veggies.veg.name }} 
{% endfor %} 

輸出

Veggie by basket order, showing name 

    a 

    c 

    b 

該輸出中沒有素食名。

我認爲這不是Django所說的那樣。我明白,我可以寫一個標籤來解決這個問題。這很醜陋。

這是一個沒有對Django開發團隊修復,按照Django ticket 12486,因爲「我們的目的是,Django的模板,可以讀取和非程序員編寫的,因此複雜的邏輯應該是視圖代碼或自定義模板標籤。」 (Luke工廠)

對於在這種情況下編寫可讀的模板代碼的一些實用建議,我很感激(我有很多不同種類的「蔬菜」來解引用)。如果我們有模板編寫人員 - 他們知道如何進行字典查找,那麼是否值得從Django中脫身?

+0

我知道你知道是怎麼回事,但我不明白爲什麼你認爲違背它在文檔中說。相反,您引用的文檔非常清晰,並且其中沒有任何內容表示它會將變量用作字典鍵。 –

回答

0

Django正在阻止您在模板中添加快速入侵來解決您的問題,因爲它會強制模板作者和視圖作者之間分離。想象一下,您銷售了10,000種不同的蔬菜,並將它們保存在數據庫表中。您是否真的想要將所有10,000種蔬菜的字典傳遞到模板中以啓用您所描述的內容?

如果你用真正的模型而不是類和字典構建這個例子,你可能已經有了你想要的東西:一個「籃子」將是一個對象,它有一個外部鍵對「素食」的引用,所以basket_item.veggie將參照在素食表中的一排(呃,沒有雙關語)。您可以簡單地通過籃子,並且從模板中引用時,素食項目將按需填充。爲了提高效率,您可能最終在獲取購物籃商品時使用.select_related,以便在單個SQL查詢中預填充素食物品。

+0

由於快速入侵,問題不表達。我有一個主迭代器生成節點,幾個對象的字典被引用。這些數據結構在plpgsql函數中進行了高度優化,運行速度比Django的ORM快幾個數量級。我想你是在說「不要那樣使用Django的代碼」;我不同意這種做法。 – rorycl

2

Django的模板引擎在您的for循環中將veg作爲字符串對待,但您試圖將其用作表達式的一部分。雖然Django的模板引擎有時會遇到障礙,但您所做的只是無法驗證。你想要做的是獲得veggies與包含在對象veg名稱的屬性,點符號不工作的方式無論是在Python或Django的模板。當你說veggies.veg,它是尋找一個名爲veg對蔬菜的屬性,而不是命名ab,或c。這不是Django模板引擎的缺陷;這就是Python(以及我所知道的每種語言)的工作原理。

相反,剛吸起來,寫一個模板標籤訪問屬性,按名稱,任意物體,或者通過模板,不需要在模板中的那種邏輯的籃子。

+0

感謝您的評論,丹尼爾。顯然你說的是它的工作原理,但是規範指出dot *表示查找* - 所以它不能與Python代碼相提並論。我認爲你的「吮吸」評論總結了這種情況。 – rorycl

+0

中性化模板邏輯的宗教信仰有時是令人討厭的,但有時候9/10倍的方法可以通過將邏輯放在視圖中來實現你想要的內容,而在不可行的情況下,你總是可以創建作業的標籤或過濾器。 –

1

Django的方式做到這一點是準備數據結構的視圖渲染(我認爲這就是爲什麼是「意見」被稱爲在Django「視圖」的原因之一),例如

basket = [veggies[veg_id] for veg_id in basket_id_list] 

然後

{% for veg in basket %} 
    {{ veg.name }} 
{% endfor %} 

所以傳遞要呈現的結構,而不是你得到的地方結構。 django認爲模板編寫者愚蠢的人無法理解字典查找(或者一些python代碼)是不正確的,django認爲變量字典查找(以及任意的python代碼)對於模板邏輯來說太複雜,並且有理由爲了那個原因。我個人沒有發現你的模板代碼片段非常可讀,但這是個人喜好。

如果你不同意這個意識形態或者它限制你的任務,那麼很容易使用模板過濾器(無論如何都無法區分dct [var]和dct ['var']) ,過濾器只是一個單一的內容,在django本身沒有任何好處),或者,如果這種意識形態真的很噁心,可以切換到不同的模板引擎,比如jinja2。

+1

問題是,並不是所有的數據結構都是線性的或者包含在您建議的方式中,或者可能需要低效的迭代才能將它們轉換爲獨立結構。您的評論幫助我更清楚地瞭解了這一點(至少對我自己來說) - 謝謝。 – rorycl