{"title":"How to override templates","version":"4.1","locale":"zh-hans","docname":"howto/overriding-templates","url":"/zh-hans/4.1/howto/overriding-templates/","canonical":"https://djangodocs.dev/zh-hans/4.1/howto/overriding-templates/","summary":"在项目中，你可以想要在另一个 Django 应用中重写模板，不论它是第三方应用或 contrib 应用，例如 django.contrib.admin 。你可以将重写的模板置于工程的模板目录或应用的模板目录。 若应用和工程的模板模板都包含被重写的模板，默认的 Django…","html":"<h1>How to override templates<a class=\"heading-anchor\" href=\"#how-to-override-templates\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>在项目中，你可以想要在另一个 Django 应用中重写模板，不论它是第三方应用或 contrib 应用，例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.admin</span></code>。你可以将重写的模板置于工程的模板目录或应用的模板目录。</p>\n<p>若应用和工程的模板模板都包含被重写的模板，默认的 Django 模板加载器会先尝试加载工程目录下的模板。换句话说，先查找 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DIRS</span></code></a>，其次 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APP_DIRS</span></code></a>。</p>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<p>阅读 <span class=\"xref std std-ref\">重写内置视图模板</span> 若你正在找相关资料。</p>\n</aside>\n<section id=\"overriding-from-the-project-s-templates-directory\">\n<h2>重写来自工程目录的模板<a class=\"heading-anchor\" href=\"#overriding-from-the-project-s-templates-directory\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>首先，我们探索用在工程模板目录创建替代模板的方法。</p>\n<p>假设你正在重写第三方应用 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog</span></code> 的模板，该应用提供了 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/post.html</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/list.html</span></code> 模板。工程关键配置如下:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">pathlib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Path</span>\n\n<span class=\"n\">BASE_DIR</span> <span class=\"o\">=</span> <span class=\"n\">Path</span><span class=\"p\">(</span><span class=\"vm\">__file__</span><span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">resolve</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">parent</span><span class=\"o\">.</span><span class=\"n\">parent</span>\n\n<span class=\"n\">INSTALLED_APPS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"o\">...</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;blog&#39;</span><span class=\"p\">,</span>\n    <span class=\"o\">...</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n\n<span class=\"n\">TEMPLATES</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;BACKEND&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.template.backends.django.DjangoTemplates&#39;</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;DIRS&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"n\">BASE_DIR</span> <span class=\"o\">/</span> <span class=\"s1\">&#39;templates&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;APP_DIRS&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"o\">...</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>若用模板工程模板创建工程，则 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-TEMPLATES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TEMPLATES</span></code></a> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">BASE_DIR</span></code> 早已存在。需要修改的配置是 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-TEMPLATES-DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DIRS</span></code></a>。</p>\n<p>这些配置假定在工程根目录下有个 <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> 目录。要重写 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog</span></code> 应用的模板，在 <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> 目录中创建一个文件夹，然后将以下模板文件添加至该目录：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>templates/\n    blog/\n        list.html\n        post.html\n</code></pre></div>\n<p>模板加载器会先查找 <code class=\"docutils literal notranslate\"><span class=\"pre\">DIRS</span></code> 目录下的模板。当 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog</span></code> 应用中的视图要求 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/post.html</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/list.html</span></code> 模板，加载器会返回你刚创建的文件。</p>\n</section>\n<section id=\"overriding-from-an-app-s-template-directory\">\n<h2>重写来自应用模板目录的模板<a class=\"heading-anchor\" href=\"#overriding-from-an-app-s-template-directory\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>由于重写的模板位于工程应用之外，更常见的做法是使用第一个方法，然后将重写的模板置于工程模板目录。然而，如果你偏爱将重写的模板放入应用模板目录，也是可以的。</p>\n<p>首先，确保模板配置会搜索应用模板目录:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">TEMPLATES</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"p\">{</span>\n        <span class=\"o\">...</span><span class=\"p\">,</span>\n        <span class=\"s1\">&#39;APP_DIRS&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"o\">...</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">]</span>\n</code></pre></div>\n<p>若你想重写名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/list.html</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">blog/post.html</span></code> 的模板，并将它们置于名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">myapp</span></code> 的应用中，那么目录结构应该看起来像这样：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>myapp/\n    templates/\n        blog/\n            list.html\n            post.html\n</code></pre></div>\n<p>当 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-TEMPLATES-APP_DIRS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">APP_DIRS</span></code></a> 置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，模板加载器会深入应用的模板目录查找模板。</p>\n</section>\n<section id=\"extending-an-overridden-template\">\n<span id=\"id1\"></span><h2>扩展复写模板<a class=\"heading-anchor\" href=\"#extending-an-overridden-template\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>当你配置好你的模板加载器后，你可以使用 <code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">extends</span> <span class=\"pre\">%}</span></code> 模板标签的同时来覆盖它。这样可以让你不用重写整个模板就可以做一些微小的改动。</p>\n<p>举个例子，你可以使用这项技术在 <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> 管理员模板中添加自定义的Logo：</p>\n<blockquote>\n<div><figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">templates/admin/base_site.html</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Django template code\"><code> <span class=\"cp\">{%</span> <span class=\"k\">extends</span> <span class=\"s2\">&quot;admin/base_site.html&quot;</span> <span class=\"cp\">%}</span>\n\n <span class=\"cp\">{%</span> <span class=\"k\">block</span> <span class=\"nv\">branding</span> <span class=\"cp\">%}</span>\n     <span class=\"p\">&lt;</span><span class=\"nt\">img</span> <span class=\"na\">src</span><span class=\"o\">=</span><span class=\"s\">&quot;link/to/logo.png&quot;</span> <span class=\"na\">alt</span><span class=\"o\">=</span><span class=\"s\">&quot;logo&quot;</span><span class=\"p\">&gt;</span>\n     <span class=\"cp\">{{</span> <span class=\"nb\">block</span><span class=\"nv\">.super</span> <span class=\"cp\">}}</span>\n <span class=\"cp\">{%</span> <span class=\"k\">endblock</span> <span class=\"cp\">%}</span>\n</code></pre></figure>\n</div></blockquote>\n<p>关键注意点：</p>\n<ul class=\"simple\">\n<li><p>这个例子创建了使用配置好的项目级 <code class=\"docutils literal notranslate\"><span class=\"pre\">templates</span></code> 目录创建了管理员文件 <code class=\"docutils literal notranslate\"><span class=\"pre\">templates/admin/base_site.html</span></code> 来覆盖管理员文件 <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> 。</p></li>\n<li><p>新的管理员模板拓展了  <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> 并覆盖了它。</p></li>\n<li><p>新模板只是替换了 <code class=\"docutils literal notranslate\"><span class=\"pre\">branding</span></code> 区域，添加了一个自定义的Logo，和使用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">block.super</span></code> 以继承原有的内容。</p></li>\n<li><p>被继承的管理员模板 <code class=\"docutils literal notranslate\"><span class=\"pre\">admin/base_site.html</span></code> 的其他内容没有变化。</p></li>\n</ul>\n<p>这个技术起作用是因为当解析到 <code class=\"docutils literal notranslate\"><span class=\"pre\">extends</span></code> 标签时模板加载器不认为这是已经加载过的有覆盖的模板（管理员模板位于 <code class=\"docutils literal notranslate\"><span class=\"pre\">templates/admin/base_site.html</span></code>）。与 <code class=\"docutils literal notranslate\"><span class=\"pre\">block.super</span></code> 的结合是对原有内容做很小的改动的有力技术。</p>\n</section>","rootId":"how-to-override-templates","toc":[{"title":"重写来自工程目录的模板","anchor":"overriding-from-the-project-s-templates-directory","children":[]},{"title":"重写来自应用模板目录的模板","anchor":"overriding-from-an-app-s-template-directory","children":[]},{"title":"扩展复写模板","anchor":"extending-an-overridden-template","children":[]}],"breadcrumbs":[{"docname":"howto/index","title":"操作指南","url":"/zh-hans/4.1/howto/"}],"prev":{"docname":"howto/outputting-pdf","title":"How to create PDF files","url":"/zh-hans/4.1/howto/outputting-pdf/"},"next":{"docname":"howto/static-files/index","title":"How to manage static files (e.g. images, JavaScript, CSS)","url":"/zh-hans/4.1/howto/static-files/"},"formats":{"html":"/zh-hans/4.1/howto/overriding-templates/","markdown":"/zh-hans/4.1/howto/overriding-templates.md","json":"/zh-hans/4.1/howto/overriding-templates.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/howto/overriding-templates.txt","official":"https://docs.djangoproject.com/zh-hans/4.1/howto/overriding-templates/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}