У меня есть сайт с несколькими сотнями страниц, где, возможно, 75% страниц являются статическим контентом, а остальные соответствуют типичной модели "веб-приложения". Я предпочитаю Django, поэтому я в основном искал решения, основанные на этом.
Контент сделан на заказ - большинство страниц имеют мало общего с базовым хромом сайта, и достаточно сложны, чтобы их было проще писать в HTML, чем пытаться заставить текстовый редактор получить правильный вывод. Таким образом, в настоящее время я двигаюсь в направлении определения содержимого в шаблонах - у меня есть одно представление и я использую входящий путь в качестве пути шаблона. Это сохраняет каждую страницу на сайте как страницу в файловой системе (легко просматривать, легко отслеживать в управлении версиями), но позволяет каждой странице использовать любое количество общих элементов (верхние и нижние колонтитулы, навигацию) и вставлять свои собственные данные в их по мере необходимости.
Впрочем, это увязло во многих деталях. Например:
- Обмен данными страницы с другими страницами. Например, заголовок, заданный страницей, должен отображаться в навигационных меню на других страницах и т. Д. Я нашел этот вопрос о получении значения блока из шаблона, но это кажется действительно запутанным (и не масштабируемым) .
- Схожая проблема: если я определяю что-то как блок, я могу использовать его только один раз. Я видел пример {% block title%} - который обычно проходит в нескольких местах на странице - несколько раз в SO без отличного решения.
- Множественное / гибкое наследование. Для хлебных крошек я мог бы хотеть наследовать от предка страницы, но для макета я бы, вероятно, хотел бы наследовать от чего-то другого (например, базовый шаблон с одним столбцом или с двумя столбцами).
Я думаю, что эти конкретные проблемы могут быть решены сами по себе, в основном с помощью включений и пользовательских тегов шаблонов, но, глядя вниз по этому пути, я вижу взломы, сложенные поверх хаков, которых я хотел бы избежать - это нужно довольно простая и легко подавляемая система.
В процессе изучения я наткнулся на Hyde , который, похоже, решает многие из этих проблем. В частности, мне очень нравится, что он имеет структуру сайта и дает страницам несколько хороших инструментов для навигации.
Но у меня все еще есть все динамические части, которые действительно должны соответствовать без проблем. Поэтому все, что я делаю для страниц контента, должно быть действительно доступно для любого шаблона, который является частью динамического приложения. Кроме того, одна вещь, которая мне действительно нравится в подходе «каждая страница в шаблоне» - это то, что я могу изменить обработку любой конкретной страницы, просто добавив ее путь к urls.py и указав настраиваемое представление.
Есть ли хорошее решение для этого типа использования? В более общем смысле, это не то, что Джанго не следует просить делать? Мне приходит в голову, что я пытаюсь использовать файловую систему в качестве базы данных 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 %}
Это работает, но кажется непрозрачным и хрупким:
- Глобальный dict нужно как-то добавить - сейчас я делаю это в представлении, но я думаю, что лучше использовать процессор с собственным контекстом
- Это должно быть в унаследованном блоке, чтобы он действительно отображал
- Поскольку нам иногда нужны данные супер (например, для хлебных крошек), он должен вызывать {{block.super}}, но он должен быть в правильном порядке, чтобы данные супер не могли перезаписать данные целевой страницы.
Мне просто кажется, что я работаю против того, как Джанго хочет работать, и я надеялся, что есть какой-то лучший способ справиться с такого рода вещами, которые мне не хватало.