{"title":"进阶指南：如何编写可重用程序","version":"3.2","locale":"zh-hans","docname":"intro/reusable-apps","url":"/zh-hans/3.2/intro/reusable-apps/","canonical":"https://djangodocs.dev/zh-hans/3.2/intro/reusable-apps/","summary":"这篇进阶指南从 教程 7 结尾的地方继续讲起。我们将会把我们的 Web-poll 放进一个独立的 Python 包中，以便你在新的项目中重用它或将它与他人分享。 如果你尚未完成教程 1-7，我们推荐你先浏览一遍教程，这样你的样例工程会和下面的一致。 可重用性很重要 Link to this heading #…","html":"<h1>进阶指南：如何编写可重用程序<a class=\"heading-anchor\" href=\"#advanced-tutorial-how-to-write-reusable-apps\"><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/3.2/intro/tutorial07/\"><span class=\"doc\">教程 7</span></a> 结尾的地方继续讲起。我们将会把我们的 Web-poll 放进一个独立的 Python 包中，以便你在新的项目中重用它或将它与他人分享。</p>\n<p>如果你尚未完成教程 1-7，我们推荐你先浏览一遍教程，这样你的样例工程会和下面的一致。</p>\n<section id=\"reusability-matters\">\n<h2>可重用性很重要<a class=\"heading-anchor\" href=\"#reusability-matters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>设计，构建，测试以及维护一个 web 应用要做很多的工作。很多 Python 以及 Django 项目都有一些常见问题。如果我们能保存并利用这些重复的工作岂不是更好？</p>\n<p>可重用性是 Python 的根本。<a class=\"reference external\" href=\"https://pypi.python.org/pypi\">The Python Package Index (PyPI)</a> 有许大量的包，都可被用在你自己的 Python 项目中。同样可以在 <a class=\"reference external\" href=\"https://djangopackages.org\">Django Packages</a> 中查找已发布的可重用应用，也可将其引入到你的项目中。Django 本身也是一个 Python 包，也就是说你可以将已有的 Python 包或 Django 应用并入你的项目。你只需要编写属于你的那部分即可。</p>\n<p>假设你现在创建了一个新的项目，并且需要一个类似我们之前做的投票应用。你该如何复用这个应用呢？庆幸的是，其实你已经知道了一些。在 <a class=\"reference internal\" href=\"/zh-hans/3.2/intro/tutorial01/\"><span class=\"doc\">教程 1</span></a>，我们使用过 <code class=\"docutils literal notranslate\"><span class=\"pre\">include</span></code> 从项目级别的 URLconf 分割出 polls。在本教程中，我们将进一步使这个应用易用于新的项目中，并发布给其他人安装使用。</p>\n<aside class=\"admonition-package-app admonition\">\n<p class=\"admonition-title\">包？应用？</p>\n<p>一个 <a class=\"reference external\" href=\"https://docs.python.org/3/glossary.html#term-package\" title=\"(in Python v3.14)\"><span class=\"xref std std-term\">package</span></a> 提供了一组关联的 Python 代码的简单复用方式。一个包（“模块”）包含了一个或多个 Python 代码文件。</p>\n<p>一个包通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">import</span> <span class=\"pre\">foo.bar</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">from</span> <span class=\"pre\">foo</span> <span class=\"pre\">import</span> <span class=\"pre\">bar</span></code> 的形式导入。一个目录（例如 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>）要成为一个包，它必须包含一个特定的文件 <code class=\"docutils literal notranslate\"><span class=\"pre\">__init__.py</span></code>，即便这个文件是空的。</p>\n<p>Django <em>应用</em> 仅仅是专用于 Django 项目的 Python 包。应用会按照 Django 规则，创建好 <code class=\"docutils literal notranslate\"><span class=\"pre\">models</span></code>,  <code class=\"docutils literal notranslate\"><span class=\"pre\">tests</span></code>,  <code class=\"docutils literal notranslate\"><span class=\"pre\">urls</span></code>, 以及 <code class=\"docutils literal notranslate\"><span class=\"pre\">views</span></code> 等子模块。</p>\n<p>稍后，我们将解释术语 <em>打包</em> ——为了方便其它人安装 Python 包的处理流程。我知道，这可能会使你感到一点点迷惑。</p>\n</aside>\n</section>\n<section id=\"your-project-and-your-reusable-app\">\n<h2>你的项目和可复用应用<a class=\"heading-anchor\" href=\"#your-project-and-your-reusable-app\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\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\">mysite</span><span class=\"o\">/</span>\n    <span class=\"n\">manage</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">mysite</span><span class=\"o\">/</span>\n        <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">urls</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">asgi</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">wsgi</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">polls</span><span class=\"o\">/</span>\n        <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">migrations</span><span class=\"o\">/</span>\n            <span class=\"fm\">__init__</span><span class=\"o\">.</span><span class=\"n\">py</span>\n            <span class=\"mi\">0001</span><span class=\"n\">_initial</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">static</span><span class=\"o\">/</span>\n            <span class=\"n\">polls</span><span class=\"o\">/</span>\n                <span class=\"n\">images</span><span class=\"o\">/</span>\n                    <span class=\"n\">background</span><span class=\"o\">.</span><span class=\"n\">gif</span>\n                <span class=\"n\">style</span><span class=\"o\">.</span><span class=\"n\">css</span>\n        <span class=\"n\">templates</span><span class=\"o\">/</span>\n            <span class=\"n\">polls</span><span class=\"o\">/</span>\n                <span class=\"n\">detail</span><span class=\"o\">.</span><span class=\"n\">html</span>\n                <span class=\"n\">index</span><span class=\"o\">.</span><span class=\"n\">html</span>\n                <span class=\"n\">results</span><span class=\"o\">.</span><span class=\"n\">html</span>\n        <span class=\"n\">tests</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">urls</span><span class=\"o\">.</span><span class=\"n\">py</span>\n        <span class=\"n\">views</span><span class=\"o\">.</span><span class=\"n\">py</span>\n    <span class=\"n\">templates</span><span class=\"o\">/</span>\n        <span class=\"n\">admin</span><span class=\"o\">/</span>\n            <span class=\"n\">base_site</span><span class=\"o\">.</span><span class=\"n\">html</span>\n</code></pre></div>\n<p>你在 <span class=\"xref std std-doc\">教程 7</span> 中创建了 <code class=\"docutils literal notranslate\"><span class=\"pre\">mysite/templates</span></code>，在 <span class=\"xref std std-doc\">教程 3</span> 中创建了 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/templates</span></code>。现在也许更清楚为什么我们选择为项目和应用程序设置单独的模板目录：所有属于 polls 应用程序的部分都在 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 中。这使得应用程序自成一体，更容易放到一个新项目中。</p>\n<p>目录 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 现在可以被拷贝至一个新的 Django 工程，且立刻被复用。不过现在还不是发布它的时候。为了这样做，我们需要打包这个应用，便于其他人安装它。</p>\n</section>\n<section id=\"installing-some-prerequisites\">\n<span id=\"installing-reusable-apps-prerequisites\"></span><h2>安装必须环境<a class=\"heading-anchor\" href=\"#installing-some-prerequisites\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>目前，打包 Python 程序需要工具，有许多工具可以完成此项工作。在此教程中，我们将使用 <a class=\"reference external\" href=\"https://pypi.org/project/setuptools/\">setuptools</a> 来打包我们的程序。这是推荐的打包工具（与 <code class=\"docutils literal notranslate\"><span class=\"pre\">发布</span></code> 分支合并）。我们仍旧使用 <a class=\"reference external\" href=\"https://pypi.org/project/pip/\">pip</a> 来安装和卸载这个工具。现在，你需要安装这两个包。如果你需要帮助，你可以参考 <a class=\"reference internal\" href=\"/zh-hans/3.2/topics/install/#installing-official-release\"><span class=\"std std-ref\">如何通过 pip 安装 Django</span></a>，你可以通过相同的方式安装 <code class=\"docutils literal notranslate\"><span class=\"pre\">setuptools</span></code>。</p>\n</section>\n<section id=\"packaging-your-app\">\n<h2>打包你的应用<a class=\"heading-anchor\" href=\"#packaging-your-app\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Python 的 <em>打包</em> 将以一种特殊的格式组织你的应用，意在方便安装和使用这个应用。Django 本身就被打包成类似的形式。对于一个小应用，例如 polls，这不会太难。</p>\n<ol class=\"arabic\">\n<li><p>首先，在你的 Django 项目目录外创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls</span></code> 的文件夹，用于盛放 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code>。</p>\n<aside class=\"admonition-choosing-a-name-for-your-app admonition\">\n<p class=\"admonition-title\">为你的应用选择一个名字</p>\n<p>当为你的包选一个名字时，避免使用像 PyPI 这样已存在的包名，否则会导致冲突。当你创建你的发布包时，可以在模块名前增加 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-</span></code> 前缀，这是一个很常用也很有用的避免包名冲突的方法。同时也有助于他人在寻找 Django 应用时确认你的 app 是 Django 独有的。</p>\n<p>应用标签（指用点分隔的包名的最后一部分）在 <a class=\"reference internal\" href=\"/zh-hans/3.2/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 中 <em>必须</em> 是独一无二的。避免使用任何与 Django <a class=\"reference internal\" href=\"/zh-hans/3.2/ref/contrib/\"><span class=\"doc\">contrib packages</span></a> 文档中相同的标签名，比如 <code class=\"docutils literal notranslate\"><span class=\"pre\">auth</span></code>，<code class=\"docutils literal notranslate\"><span class=\"pre\">admin</span></code>，<code class=\"docutils literal notranslate\"><span class=\"pre\">messages</span></code>。</p>\n</aside>\n</li>\n<li><p>将 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 目录移入 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls</span></code> 目录。</p></li>\n<li><p>创建一个名为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/README.rst</span></code> 的文件，包含以下内容：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"rst\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/README.rst</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Rst</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=\"Rst code\"><code><span class=\"gh\">=====</span>\n<span class=\"gh\">Polls</span>\n<span class=\"gh\">=====</span>\n\nPolls is a Django app to conduct Web-based polls. For each question,\nvisitors can choose between a fixed number of answers.\n\nDetailed documentation is in the &quot;docs&quot; directory.\n\n<span class=\"gh\">Quick start</span>\n<span class=\"gh\">-----------</span>\n\n<span class=\"m\">1.</span> Add &quot;polls&quot; to your INSTALLED_APPS setting like this::\n\n    INSTALLED_APPS = [\n<span class=\"c\">        ...</span>\n<span class=\"c\">        &#39;polls&#39;,</span>\n<span class=\"c\">    ]</span>\n\n<span class=\"m\">2.</span> Include the polls URLconf in your project urls.py like this::\n\n    path(&#39;polls/&#39;, include(&#39;polls.urls&#39;)),\n\n<span class=\"m\">3.</span> Run <span class=\"s\">``python manage.py migrate``</span> to create the polls models.\n\n<span class=\"m\">4.</span> Start the development server and visit http://127.0.0.1:8000/admin/\n   to create a poll (you&#39;ll need the Admin app enabled).\n\n<span class=\"m\">5.</span> Visit http://127.0.0.1:8000/polls/ to participate in the poll.\n</code></pre></figure>\n</li>\n<li><p>创建一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/LICENSE</span></code> 文件。选择一个非本教程使用的授权协议，但是要足以说明发布代码没有授权证书是 <em>不可能的</em> 。Django 和很多兼容 Django 的应用是以 BSD 授权协议发布的；不过，你可以自己选择一个授权协议。只要确定你选择的协议能够限制未来会使用你的代码的人。</p></li>\n<li><p>下一步我们将创建 <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.cfg</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">setup.py</span></code> 文件用于说明如何构建和安装应用的细节。关于此文件的完整介绍超出了此教程的范围，但是 <a class=\"reference external\" href=\"https://setuptools.readthedocs.io/en/latest/\">setuptools docs</a> 有详细的介绍。创建文件 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/setup.py</span></code> 包含以下内容：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"ini\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/setup.cfg</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Ini</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=\"Ini code\"><code><span class=\"k\">[metadata]</span>\n<span class=\"na\">name</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">django-polls</span>\n<span class=\"na\">version</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">0.1</span>\n<span class=\"na\">description</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">A Django app to conduct Web-based polls.</span>\n<span class=\"na\">long_description</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">file: README.rst</span>\n<span class=\"na\">url</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">https://www.example.com/</span>\n<span class=\"na\">author</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">Your Name</span>\n<span class=\"na\">author_email</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">yourname@example.com</span>\n<span class=\"na\">license</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">BSD-3-Clause</span><span class=\"w\">  </span><span class=\"c1\"># Example license</span>\n<span class=\"na\">classifiers</span><span class=\"w\"> </span><span class=\"o\">=</span>\n<span class=\"w\">    </span><span class=\"na\">Environment</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Web Environment</span>\n<span class=\"w\">    </span><span class=\"na\">Framework</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Django</span>\n<span class=\"w\">    </span><span class=\"na\">Framework</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Django :: X.Y</span><span class=\"w\">  </span><span class=\"c1\"># Replace &quot;X.Y&quot; as appropriate</span>\n<span class=\"w\">    </span><span class=\"na\">Intended Audience</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Developers</span>\n<span class=\"w\">    </span><span class=\"na\">License</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: OSI Approved :: BSD License</span>\n<span class=\"w\">    </span><span class=\"na\">Operating System</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: OS Independent</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python :: 3</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python :: 3 :: Only</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python :: 3.6</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python :: 3.7</span>\n<span class=\"w\">    </span><span class=\"na\">Programming Language</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Python :: 3.8</span>\n<span class=\"w\">    </span><span class=\"na\">Topic</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Internet :: WWW/HTTP</span>\n<span class=\"w\">    </span><span class=\"na\">Topic</span><span class=\"w\"> </span><span class=\"o\">:</span><span class=\"s\">: Internet :: WWW/HTTP :: Dynamic Content</span>\n\n<span class=\"k\">[options]</span>\n<span class=\"na\">include_package_data</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">true</span>\n<span class=\"na\">packages</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">find:</span>\n<span class=\"na\">python_requires</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">&gt;=3.6</span>\n<span class=\"na\">install_requires</span><span class=\"w\"> </span><span class=\"o\">=</span>\n<span class=\"w\">    </span><span class=\"na\">Django &gt;</span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">X.Y</span><span class=\"w\">  </span><span class=\"c1\"># Replace &quot;X.Y&quot; as appropriate</span>\n</code></pre></figure>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/setup.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</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=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">setuptools</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">setup</span>\n\n<span class=\"n\">setup</span><span class=\"p\">()</span>\n</code></pre></figure>\n</li>\n<li><p>默认情况下，包中仅包含 Python 模块和包。 要包含其他文件，我们需要创建一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">MANIFEST.in</span></code> 文件。 上一步中提到的 setuptools 文档更详细地讨论了这个文件。 要包含模板、<code class=\"docutils literal notranslate\"><span class=\"pre\">README.rst</span></code> 和我们的 <code class=\"docutils literal notranslate\"><span class=\"pre\">LICENSE</span></code> 文件，创建一个文件 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/MANIFEST.in</span></code> ，其内容如下：</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"text\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/MANIFEST.in</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</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=\"Text code\"><code>include LICENSE\ninclude README.rst\nrecursive-include polls/static *\nrecursive-include polls/templates *\n</code></pre></figure>\n</li>\n<li><p>在应用中包含详细文档是可选的，但我们推荐你这样做。创建一个空目录 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/docs</span></code> 用于未来编写文档。额外添加一行至 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls/MANIFEST.in</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=\"n\">recursive</span><span class=\"o\">-</span><span class=\"n\">include</span> <span class=\"n\">docs</span> <span class=\"o\">*</span>\n</code></pre></div>\n<p>注意，现在 <code class=\"docutils literal notranslate\"><span class=\"pre\">docs</span></code> 目录不会被加入你的应用包，除非你往这个目录加几个文件。许多 Django 应用也提供他们的在线文档通过类似 <a class=\"reference external\" href=\"https://readthedocs.org\">readthedocs.org</a> 这样的网站。</p>\n</li>\n<li><p>试着构建你自己的应用包通过 <code class=\"docutils literal notranslate\"><span class=\"pre\">ptyhon</span> <span class=\"pre\">setup.py</span> <span class=\"pre\">sdist</span></code> （在 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls``目录内）。这将创建一个名为</span> <span class=\"pre\">``dist</span></code> 的目录并构建你自己的应用包， <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls-0.1.tar.gz</span></code>。</p></li>\n</ol>\n<p>更多关于打包的信息，见 Python 的 <a class=\"reference external\" href=\"https://packaging.python.org/tutorials/packaging-projects/\">关于打包和发布项目的教程</a>。</p>\n</section>\n<section id=\"using-your-own-package\">\n<h2>使用你自己的包名<a class=\"heading-anchor\" href=\"#using-your-own-package\"><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\">django-polls</span></code> 应用来修复这个问题。</p>\n<aside class=\"admonition-installing-as-a-user-library admonition\">\n<p class=\"admonition-title\">作为用户库安装</p>\n<p>以下步骤将 <code class=\"docutils literal notranslate\"><span class=\"pre\">django-polls</span></code> 以用户库的形式安装。与安装整个系统的软件包相比，用户安装具有许多优点，例如可在没有管理员访问权的系统上使用，以及防止应用包影响系统服务和其他用户。</p>\n<p>请注意，按用户安装仍然会影响以该用户身份运行的系统工具的行为，因此使用虚拟环境是更可靠的解决方案（请参见下文）。</p>\n</aside>\n<ol class=\"arabic\">\n<li><p>为了安装这个包，使用 pip (你早已 <a class=\"reference internal\" href=\"#installing-reusable-apps-prerequisites\"><span class=\"std std-ref\">安装 pip</span></a>, 对吗？):</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\">python</span> <span class=\"o\">-</span><span class=\"n\">m</span> <span class=\"n\">pip</span> <span class=\"n\">install</span> <span class=\"o\">--</span><span class=\"n\">user</span> <span class=\"n\">django</span><span class=\"o\">-</span><span class=\"n\">polls</span><span class=\"o\">/</span><span class=\"n\">dist</span><span class=\"o\">/</span><span class=\"n\">django</span><span class=\"o\">-</span><span class=\"n\">polls</span><span class=\"o\">-</span><span class=\"mf\">0.1</span><span class=\"o\">.</span><span class=\"n\">tar</span><span class=\"o\">.</span><span class=\"n\">gz</span>\n</code></pre></div>\n</li>\n<li><p>幸运的话，你的 Django 项目应该再一次正确运行。启动服务器确认这一点。</p></li>\n<li><p>通过 pip 卸载包:</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\">python</span> <span class=\"o\">-</span><span class=\"n\">m</span> <span class=\"n\">pip</span> <span class=\"n\">uninstall</span> <span class=\"n\">django</span><span class=\"o\">-</span><span class=\"n\">polls</span>\n</code></pre></div>\n</li>\n</ol>\n</section>\n<section id=\"publishing-your-app\">\n<h2>发布你的应用<a class=\"heading-anchor\" href=\"#publishing-your-app\"><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\">django-polls</span></code> 完成了打包和测试，准备好向世界分享它！如果这不是一个例子应用，你现在就可以这样做。</p>\n<ul class=\"simple\">\n<li><p>通过邮件将你的包发送给朋友。</p></li>\n<li><p>将这个包上传至你的网站。</p></li>\n<li><p>将你的包发布至公共仓库，比如 <a class=\"reference external\" href=\"https://pypi.python.org/pypi\">the Python Package Index (PyPI)</a>。 <a class=\"reference external\" href=\"https://packaging.python.org\">packaging.python.org</a> 有一个不错的 <a class=\"reference external\" href=\"https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives\">教程</a> 说明如何发布至公共仓库。</p></li>\n</ul>\n</section>\n<section id=\"installing-python-packages-with-a-virtual-environment\">\n<h2>通过虚拟环境安装 Python 包<a class=\"heading-anchor\" href=\"#installing-python-packages-with-a-virtual-environment\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>早些时候，我们以用户库的形式安装了投票应用。这样做有一些缺点。</p>\n<ul class=\"simple\">\n<li><p>修改用户库会影响你系统上的其他 Python 软件。</p></li>\n<li><p>你将不能运行此包的多个版本（或者其它用有相同包名的包）。</p></li>\n</ul>\n<p>通常，只有在维护多个 Django 项目时才会出现这些情况。当这样做时，最好的解决方法是使用 <a class=\"reference external\" href=\"https://docs.python.org/3/tutorial/venv.html\" title=\"(in Python v3.14)\"><span class=\"xref std std-doc\">venv</span></a>。使用此工具，你可以维护多个隔离的 Python 环境，每个环境都有其自己的库和包命名空间的副本。</p>\n</section>","rootId":"advanced-tutorial-how-to-write-reusable-apps","toc":[{"title":"可重用性很重要","anchor":"reusability-matters","children":[]},{"title":"你的项目和可复用应用","anchor":"your-project-and-your-reusable-app","children":[]},{"title":"安装必须环境","anchor":"installing-some-prerequisites","children":[]},{"title":"打包你的应用","anchor":"packaging-your-app","children":[]},{"title":"使用你自己的包名","anchor":"using-your-own-package","children":[]},{"title":"发布你的应用","anchor":"publishing-your-app","children":[]},{"title":"通过虚拟环境安装 Python 包","anchor":"installing-python-packages-with-a-virtual-environment","children":[]}],"breadcrumbs":[{"docname":"intro/index","title":"开始","url":"/zh-hans/3.2/intro/"}],"prev":{"docname":"intro/tutorial07","title":"编写你的第一个 Django 应用，第 7 部分","url":"/zh-hans/3.2/intro/tutorial07/"},"next":{"docname":"intro/whatsnext","title":"下一步看什么","url":"/zh-hans/3.2/intro/whatsnext/"},"formats":{"html":"/zh-hans/3.2/intro/reusable-apps/","markdown":"/zh-hans/3.2/intro/reusable-apps.md","json":"/zh-hans/3.2/intro/reusable-apps.json"},"source":"https://github.com/django/django/blob/stable/3.2.x/docs/intro/reusable-apps.txt","official":"https://docs.djangoproject.com/zh-hans/3.2/intro/reusable-apps/","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"]}