我有一個網站有幾百頁,其中可能有75%的網頁是靜態內容,其餘的則適合典型的「網絡應用程序」模型。我的偏好是Django,所以我一直在尋找基於此的解決方案。我可以在Django內部使用像Hyde這樣的東西嗎?
內容是非常定製的 - 大多數頁面幾乎沒有超出基本的網站chrome,並且足夠複雜,以HTML編寫它們變得更加簡單,而不是試圖將富文本編輯器轉換爲提供正確的輸出。所以我現在要做的方向是定義模板中的內容 - 我有一個視圖,並使用傳入路徑作爲模板路徑。這使得網站上的每個頁面成爲文件系統中的一個頁面(易於瀏覽,易於在修訂控制中進行跟蹤),但可讓每個頁面共享任意數量的常見元素(頁眉,頁腳,導航)並將其自己的數據注入他們根據需要。但是,這在很多細節中陷入了困境。例如:
- 與其他頁面共享頁面數據。例如,頁面定義的標題應顯示在其他頁面上的導航菜單中,等等。我發現this question關於從模板中獲取塊值,但這看起來真的很複雜(並且不可縮放)。
- 相關問題:如果我將某些東西定義爲塊,我只能使用它一次。我已經看到{%block title%}的例子 - 通常會在頁面的多個位置出現 - 在沒有很好的解決方案的情況下,數次出現。
- 多重/靈活繼承。對於麪包屑我可能想從頁面的祖先繼承,但是對於佈局,我可能想要從其他東西繼承(例如,一列與兩列基本模板)。
我覺得這些具體問題都自己解決的,主要是通過使用包括和自定義模板標籤,但看着這條道路我看到堆放在黑客,我想避免的頂級黑客 - 這需要成爲一個相當簡單且易於維護的系統。
在研究這些過程中,我碰到了Hyde,這似乎解決了很多這些問題。特別是,我真的很喜歡它具有網站結構的感覺,並且它爲頁面提供了一些很好的工具來瀏覽。
但我仍然有所有的動態片斷,這真的需要無縫配合。所以我爲內容頁面做的任何事情都應該適用於動態應用程序的任何模板。另外,我非常喜歡「每頁模板」方法,我可以通過將其路徑添加到urls.py並指定自定義視圖來改變任何特定頁面的處理方式。
這種類型的用例是否有很好的解決方案?更一般地說,這只是Django不應該被要求做的事情嗎?在我看來,我試圖在這裏使用文件系統作爲CMS數據庫,這似乎可能導致擴展問題,但Django似乎很好地處理和緩存模板內容,並且在查看一些現有的CMS解決方案(django-cms,feincms,fiber)我真的不喜歡有一個靜態內容解決方案和一個完全不同的交互式內容解決方案。
編輯
這裏是我使用自定義標籤來處理頁面元/配置:
- 一個字典頁面數據在頂層傳遞(從而使標籤能寫然後在堆棧中的代碼更高可以將其讀回)
- 自定義數據標籤允許頁面將數據寫入此頁面數據
- 其他自定義標籤讀取和渲染結構(導航,麪包屑等),從數據
主要部分是一個標籤,將讀取的數據(寫爲JSON)到全局字典:
class PageInfoNode(Node):
def __init__(self, page_info):
self.title = page_info['title']
self.breadcrumb_title = page_info.get('breadcrumb_title', self.title)
self.show_breadcrumb = page_info.get('show_breadcrumb', False)
self.nav_title = page_info.get('nav_title', self.breadcrumb_title)
self.side_nav = page_info.get('side_nav', None)
def render(self, context):
# 'page_info' must be set someplace higher in the context stack
page_info = context['page_info']
page_info['title'] = self.title
page_info['nav_title'] = self.nav_title
if self.show_breadcrumb:
if 'breadcrumb' in page_info:
page_info['breadcrumb'] = [self.breadcrumb_title] + page_info['breadcrumb']
else:
page_info['breadcrumb'] = [self.breadcrumb_title]
if self.side_nav != None:
page_info['side_nav'] = self.side_nav
return ''
@register.tag
def pageinfo(parser, token):
nodelist = parser.parse(('endpageinfo',))
parser.delete_first_token()
return PageInfoNode(json.loads(nodelist.render(Context())))
每個頁面將其數據,如:
{% block data %}
{{ block.super }}
{% load my_page_tags %}
{% pageinfo %}
{
"title": "My Page Title",
"show_breadcrumb": true,
"side_nav": ["/section1/page.html", "/section2/page.html"]
}
{% endpageinfo %}
{% endblock data %}
這工作,但似乎真的不透明的和脆弱的:
- 水珠al dict需要以某種方式添加 - 現在我在視圖中執行此操作,但我認爲自定義上下文處理器會更好
- 這需要位於繼承的塊中,以便實際渲染
- 因爲我們有時需要超級數據(例如。對於麪包屑),它需要調用{{block.super}},但它需要按照正確的順序保持超級數據覆蓋目標頁面的數據。
我只是覺得我正在反對Django想要操作的方式,而且我希望有一些更好的方法來處理我錯過的這種事情。
對不起,這個自定義標籤有什麼問題? – Marcin 2012-01-06 23:45:50
把你的問題放在你的問題上。 – Marcin 2012-01-09 17:38:14
如果能讓他們乾淨地工作,我很樂意使用自定義標籤。到目前爲止,我對結果並不滿意。 – Adam 2012-01-09 17:47:47