【问题标题】:Can I use something like Hyde from within Django?我可以在 Django 中使用 Hyde 之类的东西吗?
【发布时间】:2012-01-06 20:38:53
【问题描述】:

我的网站有几百个页面,其中可能 75% 的页面是静态内容,其余页面符合典型的“Web 应用程序”模型。我的偏好是 Django,所以我一直在寻找基于它的解决方案。

内容是非常定制的——除了基本的站点 chrome 之外,大多数页面几乎没有共享,并且足够复杂,用 HTML 编写它们比尝试使用富文本编辑器提供正确的输出更简单。所以我目前的方向是只定义模板中的内容——我有一个单一的视图,并使用传入路径作为模板路径。这将站点上的每个页面保持为文件系统中的一个页面(易于浏览,易于在修订控制中跟踪),但允许每个页面共享任意数量的公共元素(页眉、页脚、导航)并将其自己的数据注入根据需要。

不过,这会陷入很多细节问题。例如:

  • 与其他页面共享页面数据。例如,一个页面定义的标题应该显示在其他页面的导航菜单中,等等。我发现this question 是关于从模板中获取块值的,但这看起来真的很复杂(而且不可扩展)。
  • 相关问题:如果我将某些内容定义为块,我只能使用一次。我已经在 SO 中多次看到 {% block title %} 的示例——它通常出现在页面中的多个位置——但没有很好的解决方案。
  • 多重/灵活继承。对于面包屑,我可能想从页面的祖先继承,但对于布局,我可能想从其他东西(例如,单列与两列基本模板)继承。

我认为这些特定问题可以自行解决,主要是通过使用包含和自定义模板标签,但在这条路上我看到黑客堆积在黑客之上,我想避免这种情况 - 这需要一个相当简单且易于理解的系统。

在研究这些问题的过程中,我遇到了Hyde,它似乎解决了很多这些问题。特别是,我真的很喜欢它具有网站结构的感觉,它为页面提供了一些很好的导航工具。

但我仍然拥有所有动态部件,它们确实需要无缝匹配。因此,我为内容页面所做的任何事情都应该真正适用于作为动态应用程序一部分的任何模板。此外,我真正喜欢“每个页面一个模板”方法的一件事是,我可以通过将其路径添加到 urls.py 并指定自定义视图来更改任何特定页面的处理方式。

对于这种类型的用例有没有好的解决方案?更一般地说,这只是不应该要求 Django 做的事情吗?我突然想到,我在这里尝试将文件系统用作 CMS 数据库,这似乎可能会导致扩展问题,但 Django 似乎可以很好地处理和缓存模板内容,并且在查看了一些现有的 CMS 之后解决方案(django-cms、feincms、fiber) 我真的不喜欢为静态内容提供一种解决方案而为交互式内容提供完全不同的解决方案的想法。

编辑

这是我使用自定义标签来处理页面元数据/配置的结果:

  1. 页面数据的字典在顶层传入(以便标签可以写入其中,然后堆栈中更高的代码可以将其读回)
  2. 自定义数据标签允许页面将数据写入此页面数据
  3. 其他自定义标签从数据中读取和呈现结构(导航、面包屑等)

主要部分是一个标签,它将读取数据(以 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 %}

这可行,但它看起来真的很不透明和脆弱:

  • 需要以某种方式添加全局字典 - 现在我在视图中添加,但我想自定义上下文处理器会更好
  • 这需要在继承的块中,以便实际呈现
  • 因为我们有时需要 super 的数据(例如面包屑),所以它需要调用 {{ block.super }} 但它需要以正确的顺序来防止 super 的数据覆盖目标页面的数据。李>

我只是觉得我正在与 Django 想要的操作方式背道而驰,我希望有更好的方法来处理我所缺少的这种事情。

【问题讨论】:

  • 抱歉,这个自定义标签有什么问题?
  • 把你的问题或问题放在你的问题中。
  • 我很乐意使用自定义标签,如果我能让它们干净地工作的话。到目前为止,我对自己的结果不太满意。

标签: django django-templates hyde


【解决方案1】:

停止在您的模板中创建数据。在您的视图中创建它,将其传递给您的模板。例如,对于面包屑,添加到面包屑路径的代码没有任何理由必须存在于模板中。它可以存在于视图中,甚至更好的是,成为上下文处理器。

【讨论】:

    【解决方案2】:

    一种解决方案是采用静态站点 + 服务模型。您使用 hyde 生成静态站点,但在客户端站点上使用 javascript 处理动态内容,在服务器上使用漂亮的 REST API。

    【讨论】:

    • 这是一个“更大”的 IMO 解决方案——开发人员必须同时了解 Hyde 和 Javascript,而根据我的经验,就简化开发而言,Javascript 工具仍然不存在。我需要将其作为可以持续一段时间的解决方案出售。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多