現在我已經解決了我的問題類似fabrizioM如何建議,但有一個明顯的區別:由於菜單項演示可以(而且大部分時間,)包含HTML,我不想在present
方法中直接使用HTML標記。所以我最終實現了Python中的菜單定義,Jinja中的演示文稿,通過相互遞歸彌合了差距。
不同類型的菜單項是由不同的子類表示:
class MenuItem(object):
def present(self, macromap):
return macromap[type(self).__name__](self, macromap)
class TextLink(MenuItem):
def __init__(self, url, text):
self.url, self.text = url, text
class Section(MenuItem):
def __init__(self, text, items):
self.text, self.items = text, items
class ImageLink(MenuItem):
...
以上引用的macromap
是一個字典映射菜單項的執行其represenation宏類型。它在神社所有定義:
{% macro TextLink(l, macromap) %}
<a class="menuitem" href="{{l.url|escape}}">
{{ l.text|escape }}
</a>
{% endmacro %}
{% macro Section(s, macromap) %}
<div class="heading">{{s.text}}</div>
<ul class="items">
{% for item in s.items %}
<li>{{ item.present(macromap) }}</li>
{% endfor %}
</ul>
{% endmacro %}
{% set default_map = {'TextLink': TextLink, 'Section': Section, ...}
實際的菜單定義乾淨利落表示爲MenuItem
子樹:
main_menu = section("Main Menu", [
section("Product Line 1", [
TextLink("/products/...", "A product"),
...
]),
section(...),
])
揭開序幕演示,模板必須調用頂層部分的present
方法,傳遞宏映射以指定如何呈現菜單,例如main_menu.present(default_map)
。正如在Section
宏中最好的一樣,菜單項然後可以要求他們的孩子展示自己,其present
方法將再次調用另一個Jinja宏,以此類推。
必須明確地傳遞宏觀地圖並不十分漂亮,但它具有很大的好處:人們現在可以輕鬆呈現菜單數據的不同表示,而無需觸摸菜單定義。例如,可以定義宏映射來呈現主網站菜單,或移動設備的變體(在CSS不足的情況下),或XML站點地圖,甚至純文本版本。 (我們實際上最終使用這個系統來處理網站菜單和網站地圖案例。)
多態性確實適用於這個問題。但是,演示文稿必須包含HTML,我真的很想將它們分離出來放入Jinja模板中。您的建議提供瞭解決問題所需的最終線索,但非常感謝! –