我可以在Django中使用像Hyde这样的东西吗?

时间:2012-01-06 20:38:53

标签: django django-templates hyde

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

内容非常定制 - 大多数页面都没有超出基本的网站chrome,并且足够复杂,以便在HTML中编写它们更简单,而不是试图将富文本编辑器与正确的输出进行争论。因此,我目前的方向是仅定义模板中的内容 - 我有一个视图,并使用传入路径作为模板路径。这使网站上的每个页面都保持为文件系统中的页面(易于浏览,易于在版本控制中跟踪),但是让每个页面共享任意数量的公共元素(页眉,页脚,导航)并将其自己的数据注入他们根据需要。

尽管如此,这仍然陷入了许多细节之中。例如:

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

我认为这些具体问题可以自行解决,主要是通过使用包含和自定义模板标签,但往下看,我看到黑客堆积的黑客,我想避免 - 这需要是一个相当简单和容易grokked系统。

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

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

这种用例有一个很好的解决方案吗?更一般地说,这只是Django不应该被要求做的事情吗?在我看来,我有点试图在这里使用文件系统作为CMS数据库,这似乎可能导致扩展问题,但Django似乎很好地处理和缓存模板内容,并在查看一些现有的CMS之后解决方案(django-cms,feincms,fiber)我真的不喜欢有一个静态内容解决方案和一个完全不同的交互式内容解决方案。

修改

以下是我使用自定义标记处理页面元数据/配置的内容:

  1. 页面数据的字典在顶层传入(这样一个标签可以写入它,然后堆栈中更高的代码可以读回来)。
  2. 自定义数据标记允许页面将数据写入此页面数据
  3. 其他自定义标签从数据中读取和呈现结构(导航,面包屑等)
  4. 主要部分是一个标记,它将数据(写成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 %}
    

    这有效,但看起来真的不透明和脆弱:

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

    我只是觉得我正在反对Django想要操作的方式,我希望有一些更好的方法可以处理我丢失的这类事情。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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