进阶指南:如何编写可重用程序

这篇进阶指南从 Tutorial 7 结尾的地方继续讲起。我们将会把我们的 Web-poll 放进一个独立的 Python 包中,以便你在新的项目中重用它或将它与他人分享。

如果你尚未完成教程 1-7,我们推荐你先浏览一遍教程,这样你的样例工程会和下面的一致。

可重用性很重要

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

可重用性是Python的生存方式。 Python软件包索引(PyPI) 有很多可以在你自己的Python程序中使用的软件包。查看 Django Packages 以了解您可以整合到项目中的现有可重用应用。Django本身也只是一个Python包。这意味着您可以将现有的Python包或Django应用组合到您自己的Web项目中。您只需编写您项目独一无二的部分。

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

包?应用?

一个 package 提供了一组关联的 Python 代码的简单复用方式。一个包(“模块”)包含了一个或多个 Python 代码文件。

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

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

稍后,我们将解释术语 打包 ——为了方便其它人安装 Python 包的处理流程。我知道,这可能会使你感到一点点迷惑。

你的项目和可复用应用

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

  1. mysite/
  2. manage.py
  3. mysite/
  4. __init__.py
  5. settings.py
  6. urls.py
  7. wsgi.py
  8. polls/
  9. __init__.py
  10. admin.py
  11. migrations/
  12. __init__.py
  13. 0001_initial.py
  14. models.py
  15. static/
  16. polls/
  17. images/
  18. background.gif
  19. style.css
  20. templates/
  21. polls/
  22. detail.html
  23. index.html
  24. results.html
  25. tests.py
  26. urls.py
  27. views.py
  28. templates/
  29. admin/
  30. base_site.html

1

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

安装必须环境

目前,打包 Python 程序需要工具,有许多工具可以完成此项工作。在此教程中,我们将使用 setuptools 来打包我们的程序。这是推荐的打包工具(与 发布 分支合并)。我们仍旧使用 pip 来安装和卸载这个工具。现在,你需要安装这两个包。如果你需要帮助,你可以参考 如何通过 pip 安装 Django,你可以通过相同的方式安装 setuptools

打包你的应用

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

  • 首先,在你的 Django 项目目录外创建一个名为 django-polls 的文件夹,用于盛放 polls

为你的应用选择一个名字

当为你的包选一个名字时,避免使用像 PyPI 这样已存在的包名,否则会导致冲突。当你创建你的发布包时,可以在模块名前增加 django- 前缀,这是一个很常用也很有用的避免包名冲突的方法。同时也有助于他人在寻找 Django 应用时确认你的 app 是 Django 独有的。

应用标签(指用点分隔的包名的最后一部分)在 INSTALLED_APPS必须 是独一无二的。避免使用任何与 Django contrib packages 文档中相同的标签名,比如 authadminmessages

  • polls 目录移入 django-polls 目录。

  • 创建一个名为 django-polls/README.rst 的文件,包含以下内容:

django-polls/README.rst

  1. =====
  2. Polls
  3. =====
  4.  
  5. Polls is a simple Django app to conduct Web-based polls. For each
  6. question, visitors can choose between a fixed number of answers.
  7.  
  8. Detailed documentation is in the "docs" directory.
  9.  
  10. Quick start
  11. -----------
  12.  
  13. 1. Add "polls" to your INSTALLED_APPS setting like this::
  14.  
  15. INSTALLED_APPS = [
  16. ...
  17. 'polls',
  18. ]
  19.  
  20. 2. Include the polls URLconf in your project urls.py like this::
  21.  
  22. path('polls/', include('polls.urls')),
  23.  
  24. 3. Run `python manage.py migrate` to create the polls models.
  25.  
  26. 4. Start the development server and visit http://127.0.0.1:8000/admin/
  27. to create a poll (you'll need the Admin app enabled).
  28.  
  29. 5. Visit http://127.0.0.1:8000/polls/ to participate in the poll.
  • 创建一个 django-polls/LICENSE 文件。选择一个非本教程使用的授权协议,但是要足以说明发布代码没有授权证书是 不可能的 。Django 和很多兼容 Django 的应用是以 BSD 授权协议发布的;不过,你可以自己选择一个授权协议。只要确定你选择的协议能够限制未来会使用你的代码的人。

  • 下一步我们将创建 setup.py 用于说明如何构建和安装应用的细节。关于此文件的完整介绍超出了此教程的范围,但是 setuptools docs 有详细的介绍。创建文件 django-polls/setup.py 包含以下内容:

django-polls/setup.py

  1. import os
  2. from setuptools import find_packages, setup
  3.  
  4. with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
  5. README = readme.read()
  6.  
  7. # allow setup.py to be run from any path
  8. os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
  9.  
  10. setup(
  11. name='django-polls',
  12. version='0.1',
  13. packages=find_packages(),
  14. include_package_data=True,
  15. license='BSD License', # example license
  16. description='A simple Django app to conduct Web-based polls.',
  17. long_description=README,
  18. url='https://www.example.com/',
  19. author='Your Name',
  20. author_email='yourname@example.com',
  21. classifiers=[
  22. 'Environment :: Web Environment',
  23. 'Framework :: Django',
  24. 'Framework :: Django :: X.Y', # replace "X.Y" as appropriate
  25. 'Intended Audience :: Developers',
  26. 'License :: OSI Approved :: BSD License', # example license
  27. 'Operating System :: OS Independent',
  28. 'Programming Language :: Python',
  29. 'Programming Language :: Python :: 3.5',
  30. 'Programming Language :: Python :: 3.6',
  31. 'Topic :: Internet :: WWW/HTTP',
  32. 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
  33. ],
  34. )
  • 默认包中只包含 Python 模块和包。为了包含额外文件,我们需要创建一个名为 MANIFEST.in 的文件。上一步中关于 setuptools 的文档详细介绍了这个文件。为了包含模板、README.rst 和我们的 LICENSE 文件,创建文件 django-polls/MANIFEST.in 包含以下内容:

django-polls/MANIFEST.in

  1. include LICENSE
  2. include README.rst
  3. recursive-include polls/static *
  4. recursive-include polls/templates *
  • 在应用中包含详细文档是可选的,但我们推荐你这样做。创建一个空目录 django-polls/docs 用于未来编写文档。额外添加一行至 django-polls/MANIFEST.in
  1. recursive-include docs *

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

  • 试着构建你自己的应用包通过 ptyhon setup.py sdist (在 django-polls目录内)。这将创建一个名为dist 的目录并构建你自己的应用包, django-polls-0.1.tar.gz

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

使用你自己的包名

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

作为用户库安装

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

注意,用户安装仍然会影响以这个用户身份运行的系统工具,所以 virtualenv 是一个更强大的解决方案(如下所示)。

  • 为了安装这个包,使用 pip (你早已 安装 pip, 对吗?):
  1. pip install --user django-polls/dist/django-polls-0.1.tar.gz
  • 幸运的话,你的 Django 项目应该再一次正确运行。启动服务器确认这一点。

  • 通过 pip 卸载包:

  1. pip uninstall django-polls

发布你的应用

现在,你已经对 django-polls 完成了打包和测试,准备好向世界分享它!如果这不是一个例子应用,你现在就可以这样做。

通过 virtualenv 安装 Python 包

早些时候,我们以用户库的形式安装了投票应用。这样做有一些缺点。

  • 修改用户库会影响你系统上的其他 Python 软件。
  • 你将不能运行此包的多个版本(或者其它用有相同包名的包)。一般来说,这些状况只在你同时运行多个 Django 项目时出现。当这个问题出现时,最好的解决办法是使用 virtualenv。这个工具允许你同时运行多个相互独立的Python环境,每个环境都有各自库和应用包命名空间的拷贝。