Django DRY - 如何在 Django 模板中扩展两个 .html 文件?

Posted

技术标签:

【中文标题】Django DRY - 如何在 Django 模板中扩展两个 .html 文件?【英文标题】:Django DRY - How to extend two .html files inside a Django Template? 【发布时间】:2021-02-03 23:53:49 【问题描述】:

我想要什么?

我想在addstudents.html 内扩展cards/apps.html,这样我就不需要多次编写代码。如何在 DJANGO 模板中扩展多个 .html 文件?

我遇到的错误

'extends' 在同一个模板中不能出现多次

怎么办?

注意:我不想使用% include %,因为情况/条件不合适。

您可能需要的一些信息...

内部卡片/apps.html

<div class="card shadow mb-4">
<div class="card-header py-3">
    <h6 class="m-0 font-weight-bold text-primary">card_title</h6>
</div>
<div class="card-body">
    % block card_body %
    
    % endblock %
</div>

addstudents.html 内

% extends 'layouts/panel.html' %
% extends 'apps/card.html' %
% load static %
% block content %

% with card_title='My Card TITLE' %
% block card_body %
...SOME FORM, .... SOME PARAGRAPH
% endblock %

% endblock %

layouts/panel.html 里面有什么

layouts/panel.html 包含一些菜单和导航栏项[包括 CSS、引导程序和 JS 依赖项]。

apps/card.html 是什么?

apps/card.html 包含 HTML 和 Bootstrap CARD 的 code-sn-p。而且我不想多次编写此代码。这就是为什么我希望通过Django Template Tags对其进行操作。

希望您能理解

【问题讨论】:

如果可以从两个基本模板扩展,你会如何期望 Django 合并两个基本模板?我认为您的用例需要使用 include 指令。或者,您可以创建从第一个扩展的第二个基本模板,然后让您的模板扩展第二个(如果有意义)。 我想你是在说我将代码加载到 'layouts/panel.html' 中,这会使代码变得既垃圾又慢。 父模板只能有一个。如果你想在几个不同的地方渲染同一段 html,又不想重复,include 标签可以帮助你 - docs.djangoproject.com/en/3.1/ref/templates/builtins/#include 。你能解释一下为什么你不想使用它吗? 我已经告诉过你我不想使用包含。我需要在% block card_body % 中编写一些代码(如 HTML-Form)。我不能在% include % 内这样做。 Include 将加载 HTML 中的所有代码块,with 可用于传递一些不能满足我要求的变量。所以为此我想要一些像% block card_body % include 正是@Selcuk 和 Erlond 提到的这个用例。您看到的冲突可以通过改进模板和布局来解决。这感觉就像an XY problem。 【参考方案1】:

我不认为这是直接可能的。但这里有一个解决方法。在处理addstudents.html 的视图中,将has_card 作为True 添加到上下文中。

views.py

def app_students(request):
    # Your code
    return render(request, 'addstudents.html', 'has_card': True)

layouts/panel.html

[...]
% if has_card %
<div class="card shadow mb-4">
    <div class="card-header py-3">
        <h6 class="m-0 font-weight-bold text-primary">card_title</h6>
    </div>
    <div class="card-body">
        % block card_body %

        % endblock %
    </div>
</div>
% endif %
[...]

addstudents.html

% extends 'layouts/panel.html' %
% with card_title='My Card TITLE' %
% block card_body %
...SOME FORM, .... SOME PARAGRAPH
% endblock %

因此,如果 has_card 不存在,则不会有 card_body 块,但如果它确实作为真值存在,那么它会存在。

【讨论】:

'extends' 在同一个模板中不能出现多次 是的。仅扩展 panel.html,删除 card.htmlapp.html 或任何调用卡片设计的文件,如果您将 has_form 传递给您的视图,它应该可以工作。 @BishwasBhandari,你试过这个吗?它应该工作!【参考方案2】:

我不确定它是否符合您的需要。 一种方法是在不同模板之间稍微划分职责。 根据给定的信息,可以将引导程序/布局的内容放在cards/apps.html 中,并添加额外的块供孩子覆盖以处理表单和查看特定信息。

澄清可能解决问题的继承:

layouts/panel.html -> apps/card.html -> addtudents.html

apps/card.htmllayout/panel.html 覆盖 block content 并添加由 addstudents.html 使用的其他块。

它也可以被看作是:addstudents.html extends card.html,它扩展了 panel.html。 Afaik 您可以根据需要进行多次扩展,但不能在同一个模板中使用两次。

cards/apps.html

% extends 'layouts/panel.html' %
% block content %
    <div class="card shadow mb-4">
    <div class="card-header py-3">
        <h6 class="m-0 font-weight-bold text-primary">% block card_title %% endblock %</h6>
    </div>
    <div class="card-body">
        % block card_body %
        
        % endblock %
    </div>
% endblock content %

addstudents.html

% extends 'apps/card.html' %

% block card_titleMy Card TITLE% endblock card_title%
% block card_body %
...SOME FORM, .... SOME PARAGRAPH
% endblock card_body %

还值得一提的是 block.super ,如果您需要渲染“父级”,它有时会非常有用。

【讨论】:

扩展% extends 'layouts/panel.html' %怎么样 您可以多次扩展,但不能在同一个模板中扩展两次...在示例中给出了以下继承:layouts/panel.html' -> cards/apps.html -> addstudents。 html。有意义吗?

以上是关于Django DRY - 如何在 Django 模板中扩展两个 .html 文件?的主要内容,如果未能解决你的问题,请参考以下文章

Django/Python DRY:使用 Q 对象和模型属性时如何避免重复代码

Django:DRY 与逻辑分离有根本冲突吗?

以 DRY 方式创建活动/存档模型 (Django)

在多个 django 模板文件中显示相同 html 块的最佳 DRY 方法

Django 表单:为继承模型组织创建/更新表单的最 DRY 方式

带有主干路由器和 django url 的 DRY url?