ページの 75% が静的コンテンツで、残りが典型的な「Web アプリケーション」モデルに適合する数百ページのサイトがあります。私の好みは Django です。そのため、これに基づくソリューションを主に検討してきました。
コンテンツは非常にオーダーメイドです。ほとんどのページは、基本的なサイト クロム以外をほとんど共有しておらず、十分に複雑であるため、リッチ テキスト エディターを使って正しい出力を提供しようとするよりも、HTML で記述した方が簡単です。したがって、私が現在行っている方向は、テンプレートでコンテンツを定義することです。単一のビューがあり、入力パスをテンプレート パスとして使用します。これにより、サイトの各ページはファイル システム内のページとして保持されますが (参照しやすく、リビジョン管理で追跡しやすくなります)、各ページは任意の数の共通要素 (ヘッダー、フッター、ナビゲーション) を共有し、独自のデータをそれらを必要に応じて。
ただし、これは多くの詳細で行き詰まります。例えば:
- 他のページとのページ データの共有。たとえば、ページで定義されたタイトルは、他のページのナビゲーション メニューなどに表示される必要があります。テンプレートからブロック値を取得することに関するこの質問を見つけましたが、これは非常に複雑なようです (そしてスケーラブルではありません)。
- 関連する問題: 何かをブロックとして定義すると、一度しか使用できなくなります。{% block title %} の例 (通常、ページ内の複数の場所に配置される) を SO で何度か見てきましたが、優れた解決策はありません。
- 複数/柔軟な継承。ブレッドクラムの場合はページの祖先から継承したいかもしれませんが、レイアウトの場合はおそらく別のものから継承したいと思うでしょう (例: 1 列と 2 列の基本テンプレート)。
これらの特定の問題は、主にインクルードとカスタム テンプレート タグを使用して、単独で解決できると思いますが、その道を見下ろすと、回避したいハックの上にハックが積み重なっていることがわかります。これはかなり単純にする必要があります。簡単に理解できるシステム。
これらを調べる過程で、これらの問題の多くに対処しているように見えるHydeに出会いました。特に、サイト構造の感覚があり、ページをナビゲートするための優れたツールを提供することが本当に気に入っています.
しかし、シームレスにフィットする必要があるダイナミックなパーツはまだすべて持っています。したがって、コンテンツ ページに対して行うことはすべて、動的アプリケーションの一部であるすべてのテンプレートで実際に利用できるはずです。また、「各ページをテンプレートにする」アプローチで私が本当に気に入っているのは、特定のページのパスを urls.py に追加してカスタム ビューを指定するだけで、そのページの扱いを変更できることです。
このタイプのユースケースに適したソリューションはありますか? より一般的に言えば、これは Django に要求してはいけないことなのでしょうか? ここで、ファイル システムを CMS データベースとして使用しようとしているような気がしますが、これはスケーリングの問題につながる可能性がありますが、Django はテンプレート コンテンツを適切に処理およびキャッシュしているようです。ソリューション (django-cms、feincms、ファイバー) 静的コンテンツ用に 1 つのソリューションを用意し、インタラクティブ コンテンツ用にまったく別のソリューションを用意するという考えは本当に好きではありません。
編集
カスタムタグを使用してページのメタデータ/構成を処理した結果は次のとおりです。
- ページ データのディクショナリがトップ レベルで渡されます (タグがそれに書き込み、スタック内のより上位のコードがそれを読み取ることができるようにするため)。
- カスタム データ タグにより、ページはこのページ データにデータを書き込むことができます
- その他のカスタム タグは、データから構造 (ナビゲーション、ブレッドクラムなど) を読み取り、レンダリングします。
主な部分は、データ (JSON として書き込まれる) をグローバル dict に読み込むタグです。
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 %}
これは機能しますが、実際には不透明で壊れやすいようです。
- グローバル dict を何らかの方法で追加する必要があります。現在、ビューで行っていますが、カスタム コンテキスト プロセッサの方が優れていると思います。
- 実際にレンダリングされるように、これは継承されたブロックにある必要があります
- スーパーのデータが必要になる場合があるため (パンくずリストなど)、{{ block.super }} を呼び出す必要がありますが、スーパーのデータがターゲット ページのデータを上書きしないように正しい順序にする必要があります。
私は Django の操作方法に逆らっているように感じます。私が見逃していたこの種のことを処理するためのより良い方法があることを望んでいました。