Django模板继承 - 如何为不同的块使用相同的内容

Posted

技术标签:

【中文标题】Django模板继承 - 如何为不同的块使用相同的内容【英文标题】:Django template inheritance - How to use the same content for different blocks 【发布时间】:2015-04-05 00:25:58 【问题描述】:

我的 django 模板中有以下结构

我有一个theme_base.html,其他模板继承自:

[...] &lttitle&gt% block page_title_header %% endblock %&lt/title&gt [...] &lth1&gt% block page_title_body %% endblock %&lt/h1&gt

现在,大多数页面的页眉和基础相同 page_title,所以我需要在我的普通模板中做这样的事情:

% block page_title_header %当前页面的页面标题% endblock % % block page_title_body %当前页面的页面标题% endblock %

不是 DRY 并且大多数时候我忘记更新page_title_header :(

您能否推荐一种将页面标题(每个页面的标题不同,因此我不能使用默认值)传递给两个块的 DRY 方式?

更新:在 cmets 讨论后,我相信 % with % 模板标签将是我需要使用的,做这样的事情:

% 以“页面标题”为标题 % % block page_title_header % title % endblock % % block page_title_body % title % endblock % % endwith %

不幸的是,上面的不起作用,标题没有传递给块!如果我删除 % block % 并执行类似

的操作 % 以“页面标题”为标题 % 标题是 标题 % endwith %

它会正常工作的。你知道可能是什么问题吗? TIA

【问题讨论】:

【参考方案1】:

您可以在块中指定默认值,例如:

[...]
<title>% block page_title_header %Page title% endblock %</title>
[...]
<h1>% block page_title_body %Page title% endblock %</h1>

当您在普通模板中省略这些块时,将使用默认值。

【讨论】:

我知道这一点。问题是 每个 模板都有不同的标题!我会尝试改写我的问题以使其更清楚......【参考方案2】:

试试:

<title>% block page_title_header %
% if somevar_title %
 somevar_title 
% else %
Default title
% endif %
% endblock %</title>

并将 somevar_title 放在您的上下文中。在您看来:

context = 'somevar_title': Page.objects.get(pk=something).title
return render(request, self.template_name, context)

您只需要记住在要使用该模板的每个视图的上下文中添加标题。 您还可以使用基于类的视图更新上下文:

class MyClass(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(MyClass, self).get_context_data(**kwargs)
        #get your title here...whatever you need it to be
        context['somevar_title'] = Something_to_get_my_title
        return context

然后,如果您从 slug 或某种可以以通用方式解决的方式获取标题,只需子类化 MyClass,您将在上下文中拥有变量。例如,使用 Page.objects.get(pk=kwargs.get('page_id')) 之类的东西就可以解决问题(不要忘记添加逻辑来处理无效的 id)。

【讨论】:

我已经想到了这一点(使用上下文变量),但这可能会为我的模板/视图添加 更多 工作,而不仅仅是重复标题(就像我现在所做的那样),因为我需要使用您提议的 get_context_data 创建一个 PageTitleMixin,不同之处在于我将使用 context['somevar_title'] = self.page_title 而不是 context['somevar_title'] = Something_to_get_my_title。对于从 PageTitleMixin 继承的每个 CBV,我需要添加一个 page_title 属性。这是一个很好的解决方案,但是我真的更喜欢只使用模板(如果可能的话)。 要仅使用模板,您需要某种方式在某些时候访问信息。它必须在数据库、url、某处。另外,就像我说的那样,只要您始终以相同的方式获得标题(即数据库中某个模型的某些字段),您就可以将 MyClass 子类化,它就会起作用。您不需要为每个视图定义 page_title。您将标题存储在哪里? 现在?在模板里面!每个模板/视图都有自己的标题,例如“配置文件详细信息”、“配置文件更新”等...这就是为什么我提到每个视图一个标题... 我的意思是,你不能计划神奇地得到它们,你一定想把它们从某个地方拿出来……某个模型,某个 url,某个地方…… 实际上,正如我之前所说,我的大多数模板在模板中都有一个硬编码的标题。我需要写两次!这就是我想要避免的!【参考方案3】:

使用 block.super。示例:

% block page_title %
    % with "foo" as title %
         block.super 
    % endwith %
% endblock %

【讨论】:

以上是关于Django模板继承 - 如何为不同的块使用相同的内容的主要内容,如果未能解决你的问题,请参考以下文章

django上的几个页面(在不同的应用程序中)相同的块

在 Django 中使用继承的块变量作为参数创建 URL

Django 模板继承

django模板继承使用相同标签多个模板

如何告诉 Django 模板不要解析包含看起来像模板标签的代码的块?

在 django 表单向导中使用不同的模板