Django 进阶指南:编写可重用应用

这个进阶教程从 教程第 8 部分 结束的地方继续讲起。我们将会把我们的网络投票应用放进一个独立的 Python 包中,以便你在新的项目中重用它或将它与他人分享。

如果你最近没有完成教程 1-8,我们鼓励你回顾这些内容,以便你的示例项目与下面描述的项目相匹配。

可重用性很重要

设计,构建,测试以及维护一个 web 应用要做很多的工作。很多 Python 以及 Django 项目都有一些常见问题。如果我们能保存并利用这些重复的工作岂不是更好?

可重用性是 Python 的根本。Python 包索引(PyPI) 提供了大量可用于自己项目的包。同样,你可以在 Django Packages 中查找已发布的可重用应用,并将其引入项目。Django 本身也是一个 Python 包,因此你可以把已有的 Python 包或 Django 应用整合进项目,只编写属于自己的那部分代码。

假设你现在创建了一个新的项目,并且需要一个类似我们之前做的投票应用。你该如何复用这个应用呢?庆幸的是,其实你已经知道了一些。在 教程 1 ,我们使用过 include 从项目级别的 URLconf 分割出 polls。在本教程中,我们将进一步使这个应用易用于新的项目中,并发布给其他人安装使用。

包与应用

包(package) 为一组相关的 Python 代码提供了便于复用的组织方式。包是可以包含一个或多个 Python 代码文件的 Python 模块。

一个包通过 import foo.bar 或 from foo import bar 的形式导入。一个目录(例如 polls)要成为一个包,它必须包含一个特定的文件 __init__.py,即便这个文件是空的。

Django 应用 仅仅是专用于 Django 项目的 Python 包。应用会按照 Django 规则,创建好 models, tests, urls, 以及 views 等子模块。

稍后我们会解释打包这个术语:它指的是让别人可以方便地安装 Python 包的处理过程。这些相近的术语可能让人有些困惑。

你的项目和可复用应用

通过前面的教程,我们的工程应该看起来像这样:

djangotutorial/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
    polls/
        __init__.py
        admin.py
        apps.py
        migrations/
            __init__.py
            0001_initial.py
        models.py
        static/
            polls/
                images/
                    background.png
                style.css
        templates/
            polls/
                detail.html
                index.html
                results.html
        tests.py
        urls.py
        views.py
    templates/
        admin/
            base_site.html

你在 教程 7 中创建了 djangotutorial/templates,在 教程 3 中创建了 polls/templates。现在可能更清楚为什么我们选择为项目和应用程序分别设置独立的模板目录了:所有属于 polls 应用程序的内容都放在 polls 中。这使得应用程序自包含,并且更容易移植到新项目中。

目录 polls 现在可以被拷贝至一个新的 Django 工程,且立刻被复用。不过现在还不是发布它的时候。为了这样做,我们需要打包这个应用,便于其他人安装它。

安装必要工具

Python 打包领域有多种工具,选择可能令人困惑。本教程使用 setuptools 构建包。它是推荐的打包工具,已与 distribute 分支合并。我们还会使用 pip 安装和卸载包。请先安装这两个包;如需帮助,参阅 如何使用 pip 安装 Django,并用相同的方法安装 setuptools。

打包你的应用

Python 的 打包 将以一种特殊的格式组织你的应用,意在方便安装和使用这个应用。Django 本身就被打包成类似的形式。对于一个小应用,例如 polls,这不会太难。

  1. 首先,在 Django 项目之外创建一个父目录来存放包。将该目录命名为 django-polls。

为应用选择名称

选择软件包名称时,请在 PyPI 上检查以避免与现有软件包命名冲突。我们建议为软件包名称使用 django- 前缀,以标识你的软件包特定于 Django,并为你的模块名称使用相应的 django_ 前缀。例如,django-ratelimit 软件包包含 django_ratelimit 模块。

应用标签是点分包名的最后一部分,在 INSTALLED_APPS 中必须唯一。避免使用 Django contrib 包 已采用的标签,例如 auth、admin 和 messages。

  1. 将 polls 目录移动到 django-polls 目录中,并将其重命名为 django_polls。
  1. 编辑 django_polls/apps.py,使 name 指向新的模块名称,添加 label 为应用程序提供一个简短的名称,并设置 default_auto_field 以确保你的迁移不受你的可重用应用程序的用户对 DEFAULT_AUTO_FIELD 所作改动的影响。

django-polls/django_polls/apps.py

from django.apps import AppConfig


class PollsConfig(AppConfig):
    default_auto_field = "django.db.models.BigAutoField"
    name = "django_polls"
    label = "polls"
  1. 创建一个名为 django-polls/README.rst 的文件,包含以下内容:

django-polls/README.rst

============
django-polls
============

django-polls is a Django app to conduct web-based polls. For each
question, visitors can choose between a fixed number of answers.

Detailed documentation is in the "docs" directory.

Quick start
-----------

1. Add "polls" to your INSTALLED_APPS setting like this::

    INSTALLED_APPS = [
        ...,
        "django_polls",
    ]
2. Include the polls URLconf in your project urls.py like this::

    path("polls/", include("django_polls.urls")),

3. Run ``python manage.py migrate`` to create the models.

4. Start the development server and visit the admin to create a poll.

5. Visit the ``/polls/`` URL to participate in the poll.
  1. 创建 django-polls/LICENSE 文件。如何选择许可证不在本教程的讨论范围内,但代码若没有许可证,就不能作为获准使用的软件发布。Django 和许多兼容 Django 的应用采用 BSD 许可证;你可以选择自己的许可证,但应当清楚它会如何约束将来使用代码的人。
  1. 接下来我们将创建 pyproject.toml 文件,该文件详细说明了如何构建和安装应用程序。对这个文件的完整解释超出了本教程的范围,但 Python 打包用户指南 提供了很好的解释。创建 django-polls/pyproject.toml 文件,内容如下:

django-polls/pyproject.toml

[build-system]
requires = ["setuptools>83"]
build-backend = "setuptools.build_meta"

[project]
name = "django-polls"
version = "0.1"
dependencies = [
    "django>=X.Y",  # Replace "X.Y" as appropriate
]
description = "A Django app to conduct web-based polls."
readme = "README.rst"
license = "BSD-3-Clause"
requires-python = ">= 3.12"
authors = [
    {name = "Your Name", email = "yourname@example.com"},
]
classifiers = [
    "Environment :: Web Environment",
    "Framework :: Django",
    "Framework :: Django :: X.Y",  # Replace "X.Y" as appropriate
    "Intended Audience :: Developers",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Programming Language :: Python :: 3.14",
    "Topic :: Internet :: WWW/HTTP",
    "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
]

[project.urls]
Homepage = "https://www.example.com/"
  1. 默认情况下,许多常见文件和 Python 模块及包已经包含在包中。要包含额外的文件,我们需要创建一个 MANIFEST.in 文件。为了包含模板和静态文件,创建一个文件 django-polls/MANIFEST.in,内容如下:

django-polls/MANIFEST.in

recursive-include django_polls/static *
recursive-include django_polls/templates *
  1. 虽然不是必须的,但建议为你的应用程序包含详细的文档。创建一个空目录 django-polls/docs 以便将来存放文档。

注意,现在 docs 目录不会被加入你的应用包,除非你往这个目录加几个文件。许多 Django 应用也提供他们的在线文档通过类似 readthedocs.org 这样的网站。

许多 Python 项目,包括 Django 和 Python 自身,都使用 Sphinx 来构建文档。如果你选择使用 Sphinx,可以通过配置 Intersphinx 并在项目的 intersphinx_mapping 值中包含 Django 的映射值,来链接回 Django 文档:

intersphinx_mapping = {
    # ...
    "django": (
        "https://docs.djangoproject.com/en/stable/",
        None,
    ),
}

配置完成后,就可以像 Django 文档一样交叉引用具体条目,例如 :attr:`django.test.TransactionTestCase.databases`。

  1. 请确认已安装 build 包(使用 python -m pip install build 命令),然后在 django-polls 目录内运行 python -m build 尝试构建你的包。这将会创建一个名为 dist 的目录,并将你的新包构建成源码格式和二进制格式:django_polls-0.1.tar.gz 和 django_polls-0.1-py3-none-any.whl。

更多关于打包的信息,见 Python 的 关于打包和发布项目的教程 。

使用自己的包

由于我们把 polls 目录移出了项目,所以它无法工作了。我们现在要通过安装我们的新 django-polls 应用来修复这个问题。

安装到用户库

以下步骤将 django-polls 以用户库的形式安装。与安装整个系统的软件包相比,用户安装具有许多优点,例如可在没有管理员访问权的系统上使用,以及防止应用包影响系统服务和其他用户。

请注意,按用户安装仍然会影响以该用户身份运行的系统工具的行为,因此使用虚拟环境是更可靠的解决方案(请参见下文)。

  1. 为了安装这个包,使用 pip (你早已 安装 pip , 对吗?):
python -m pip install --user django-polls/dist/django_polls-0.1.tar.gz
  1. 更新 mysite/settings.py 以指向新的模块名称:
INSTALLED_APPS = [
    "django_polls.apps.PollsConfig",
    ...,
]
  1. 更新 mysite/urls.py 以指向新的模块名称:
urlpatterns = [
    path("polls/", include("django_polls.urls")),
    ...,
]
  1. 运行开发服务器以确认项目继续工作。

发布你的应用

按照上述步骤完成 django-polls 的打包与测试后,你就可以向其他人分享它。如果它不只是教程示例,现在就可以考虑以下方式:

  • 通过邮件将你的包发送给朋友。
  • 将这个包上传至你的网站。

通过虚拟环境安装 Python 包

早些时候,我们将 django-polls 安装为用户库。这样做有一些不利之处:

  • 修改用户库会影响你系统上的其他 Python 软件。
  • 你将不能运行此包的多个版本(或者其它用有相同包名的包)。

通常,只有在维护多个 Django 项目时才会出现这些情况。当这样做时,最好的解决方法是使用 venv 。使用此工具,你可以维护多个隔离的 Python 环境,每个环境都有其自己的库和包命名空间的副本。

来源:Django 6.1 官方文档,中文内容作了措辞整理。适用范围保留为原文的 6.1 文档;示例中的 X.Y 是待填写版本。示例未在本地运行。

许可证:BSD-3-Clause;Django Software Foundation 及贡献者。以下保留原许可声明。

Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of Django nor the names of its contributors may be used
       to endorse or promote products derived from this software without
       specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容