{"title":"编写你的第一个 Django 应用，第 6 部分","version":"2.1","locale":"zh-hans","docname":"intro/tutorial06","url":"/zh-hans/2.1/intro/tutorial06/","canonical":"https://djangodocs.dev/zh-hans/2.1/intro/tutorial06/","summary":"这一篇从 教程第 5 部分 结尾的地方继续讲起。在上一节中我们为网络投票应用编写了测试，而现在我们要为它加上样式和图片。 除了服务端生成的 HTML 以外，网络应用通常需要一些额外的文件——比如图片，脚本和样式表——来帮助渲染网络页面。在 Django 中，我们把这些文件统称为“静态文件”。…","html":"<h1>编写你的第一个 Django 应用，第 6 部分<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-6\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>这一篇从  <a class=\"reference internal\" href=\"/zh-hans/2.1/intro/tutorial05/\"><span class=\"doc\">教程第 5 部分</span></a>  结尾的地方继续讲起。在上一节中我们为网络投票应用编写了测试，而现在我们要为它加上样式和图片。</p>\n<p>除了服务端生成的 HTML 以外，网络应用通常需要一些额外的文件——比如图片，脚本和样式表——来帮助渲染网络页面。在 Django 中，我们把这些文件统称为“静态文件”。</p>\n<p>对于小项目来说，这个问题没什么大不了的，因为你可以把这些静态文件随便放在哪，只要服务程序能够找到它们就行。然而在大项目——特别是由好几个应用组成的大项目——中，处理不同应用所需要的静态文件的工作就显得有点麻烦了。</p>\n<p>这就是 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.staticfiles</span></code> 存在的意义：它将各个应用的静态文件（和一些你指明的目录里的文件）统一收集起来，这样一来，在生产环境中，这些文件就会集中在一个便于分发的地方。</p>\n<section id=\"customize-your-app-s-look-and-feel\">\n<h2>自定义 <em>应用</em> 的界面和风格<a class=\"heading-anchor\" href=\"#customize-your-app-s-look-and-feel\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>首先，在你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 目录下创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">static</span></code> 的目录。Django 将在该目录下查找静态文件，这种方式和 Diango 在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/</span></code> 目录下查找 template 的方式类似。</p>\n<p>Django 的 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-STATICFILES_FINDERS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATICFILES_FINDERS</span></code></a> 设置包含了一系列的查找器，它们知道去哪里找到 static 文件。<code class=\"docutils literal notranslate\"><span class=\"pre\">AppDirectoriesFinder</span></code> 是默认查找器中的一个，它会在每个 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 中指定的应用的子文件中寻找名称为 <code class=\"docutils literal notranslate\"><span class=\"pre\">static</span></code> 的特定文件夹，就像我们在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 中刚创建的那个一样。管理后台采用相同的目录结构管理它的静态文件。</p>\n<p>在你刚创建的 <code class=\"docutils literal notranslate\"><span class=\"pre\">static</span></code> 文件夹中创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 的文件夹，再在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 文件夹中创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">style.css</span></code> 的文件。换句话说，你的样式表路径应是 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static/polls/style.css</span></code>。因为 <code class=\"docutils literal notranslate\"><span class=\"pre\">AppDirectoriesFinder</span></code> 的存在，你可以在 Django 中简单地使用以 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/style.css</span></code> 的形式引用此文件，类似你引用模板路径的方式。</p>\n<aside class=\"admonition-static-file-namespacing admonition\">\n<p class=\"admonition-title\">静态文件命名空间</p>\n<p>虽然我们 <em>可以</em> 像管理模板文件一样，把 static 文件直接放入 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static</span></code> ——而不是创建另一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 的子文件夹，不过这实际上是一个很蠢的做法。Django 只会使用第一个找到的静态文件。如果你在 <em>其它</em> 应用中有一个相同名字的静态文件，Django 将无法区分它们。我们需要指引 Django 选择正确的静态文件，而最简单的方式就是把它们放入各自的 <em>命名空间</em> 。也就是把这些静态文件放入 <em>另一个</em> 与应用名相同的目录中。</p>\n</aside>\n<p>将以下代码放入样式表(<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static/polls/style.css</span></code>)：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"css\"><figcaption class=\"code-block-caption\">polls/static/polls/style.css</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Css</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=\"Css code\"><code><span class=\"nt\">li</span><span class=\"w\"> </span><span class=\"nt\">a</span><span class=\"w\"> </span><span class=\"p\">{</span>\n<span class=\"w\">    </span><span class=\"k\">color</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"kc\">green</span><span class=\"p\">;</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>下一步，在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates/polls/index.html</span></code> 的文件头添加以下内容：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"html+django\"><figcaption class=\"code-block-caption\">polls/templates/polls/index.html</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\">load</span> <span class=\"nv\">static</span> <span class=\"cp\">%}</span>\n\n<span class=\"p\">&lt;</span><span class=\"nt\">link</span> <span class=\"na\">rel</span><span class=\"o\">=</span><span class=\"s\">&quot;stylesheet&quot;</span> <span class=\"na\">type</span><span class=\"o\">=</span><span class=\"s\">&quot;text/css&quot;</span> <span class=\"na\">href</span><span class=\"o\">=</span><span class=\"s\">&quot;</span><span class=\"cp\">{%</span> <span class=\"k\">static</span> <span class=\"s1\">&#39;polls/style.css&#39;</span> <span class=\"cp\">%}</span><span class=\"s\">&quot;</span><span class=\"p\">&gt;</span>\n</code></pre></figure>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">static</span> <span class=\"pre\">%}</span></code> 模板标签会生成静态文件的绝对路径。</p>\n<p>这就是你开发所需要做的所有事情了。</p>\n<p>启动服务器(如果它正在运行中，重新启动一次):</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</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=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>runserver\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</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=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py runserver\n</code></pre></div></div></div>\n<p>重新载入``http://localhost:8000/polls/`` ，你会发现有问题的链接是绿色的 (这是Django自己的问题标注方式) ，这意味着你追加的样式表起作用了。</p>\n</section>\n<section id=\"adding-a-background-image\">\n<h2>添加一个背景图<a class=\"heading-anchor\" href=\"#adding-a-background-image\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>接着，我们会创建一个用于存在图像的目录。在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static/polls</span></code> 目录下创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">images</span></code> 的子目录。在这个目录中，放一张名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">background.gif</span></code> 的图片。换言之，在目录 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static/polls/images/background.gif</span></code> 中放一张图片。</p>\n<p>随后，在你的样式表（<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/static/polls/style.css</span></code>）中添加：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"css\"><figcaption class=\"code-block-caption\">polls/static/polls/style.css</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Css</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=\"Css code\"><code><span class=\"nt\">body</span><span class=\"w\"> </span><span class=\"p\">{</span>\n<span class=\"w\">    </span><span class=\"k\">background</span><span class=\"p\">:</span><span class=\"w\"> </span><span class=\"kc\">white</span><span class=\"w\"> </span><span class=\"nb\">url</span><span class=\"p\">(</span><span class=\"s2\">&quot;images/background.gif&quot;</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"kc\">no-repeat</span><span class=\"p\">;</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>浏览器重载 <code class=\"docutils literal notranslate\"><span class=\"pre\">http://localhost:8000/polls/</span></code>，你将在屏幕的左上角见到这张背景图。</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">Warning</p>\n<p>当然，<code class=\"docutils literal notranslate\"><span class=\"pre\">{%</span> <span class=\"pre\">static</span> <span class=\"pre\">%}</span></code> 模板标签在静态文件（例如样式表）中是不可用的，因为它们不是由 Django 生成的。你仍需要使用 <em>相对路径</em> 的方式在你的静态文件之间互相引用。这样之后，你就可以任意改变 <code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">STATIC_URL`（由</span> <span class=\"pre\">:ttag:`static</span></code> 模板标签用于生成 URL），而无需修改大量的静态文件。</p>\n</aside>\n<p>这些只是 <strong>基础</strong> 。更多关于设置和框架的资料，参考 <a class=\"reference internal\" href=\"/zh-hans/2.1/howto/static-files/\"><span class=\"doc\">静态文件解惑</span></a> 和 <a class=\"reference internal\" href=\"/zh-hans/2.1/ref/contrib/staticfiles/\"><span class=\"doc\">静态文件指南</span></a>。<a class=\"reference internal\" href=\"/zh-hans/2.1/howto/static-files/deployment/\"><span class=\"doc\">部署静态文件</span></a> 介绍了如何在真实服务器上使用静态文件。</p>\n<p>当你熟悉静态文件后，阅读 <a class=\"reference internal\" href=\"/zh-hans/2.1/intro/tutorial07/\"><span class=\"doc\">此教程的第 7 部分</span></a> 来学习如何自定义 Django 自动生成后台网页的过程。</p>\n</section>","rootId":"writing-your-first-django-app-part-6","toc":[{"title":"自定义 应用 的界面和风格","anchor":"customize-your-app-s-look-and-feel","children":[]},{"title":"添加一个背景图","anchor":"adding-a-background-image","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"开始","url":"/zh-hans/2.1/intro/"}],"prev":{"docname":"intro/tutorial05","title":"编写你的第一个 Django 应用，第 5 部分","url":"/zh-hans/2.1/intro/tutorial05/"},"next":{"docname":"intro/tutorial07","title":"编写你的第一个 Django 应用，第 7 部分","url":"/zh-hans/2.1/intro/tutorial07/"},"formats":{"html":"/zh-hans/2.1/intro/tutorial06/","markdown":"/zh-hans/2.1/intro/tutorial06.md","json":"/zh-hans/2.1/intro/tutorial06.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/intro/tutorial06.txt","official":"https://docs.djangoproject.com/zh-hans/2.1/intro/tutorial06/","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","pt-br","ko","es","el","pl"]}