进阶指南:如何编写可重用程序
这篇进阶指南从 Tutorial 7 结尾的地方继续讲起。我们将会把我们的 Web-poll 放进一个独立的 Python 包中,以便你在新的项目中重用它或将它与他人分享。
如果你尚未完成教程 1-7,我们推荐你先浏览一遍教程,这样你的样例工程会和下面的一致。
可重用性很重要
设计,构建,测试以及维护一个 web 应用要做很多的工作。很多 Python 以及 Django 项目都有一些常见问题。如果我们能保存并利用这些重复的工作岂不是更好?
可重用性是Python的生存方式。 Python软件包索引(PyPI) 有很多可以在你自己的Python程序中使用的软件包。查看 Django Packages 以了解您可以整合到项目中的现有可重用应用。Django本身也只是一个Python包。这意味着您可以将现有的Python包或Django应用组合到您自己的Web项目中。您只需编写您项目独一无二的部分。
假设你现在创建了一个新的项目,并且需要一个类似我们之前做的投票应用。你该如何复用这个应用呢?庆幸的是,其实你已经知道了一些。在 教程 1,我们使用过 include
从项目级别的 URLconf 分割出 polls。在本教程中,我们将进一步使这个应用易用于新的项目中,并发布给其他人安装使用。
包?应用?
一个 package 提供了一组关联的 Python 代码的简单复用方式。一个包(“模块”)包含了一个或多个 Python 代码文件。
一个包通过 import foo.bar
或 from foo import bar
的形式导入。一个目录(例如 polls
)要成为一个包,它必须包含一个特定的文件 init.py
,即便这个文件是空的。
Django 应用 仅仅是专用于 Django 项目的 Python 包。应用会按照 Django 约定,创建好 models
, tests
, urls
, 以及 views
等子模块。
稍后,我们将解释术语 打包 ——为了方便其它人安装 Python 包的处理流程。我知道,这可能会使你感到一点点迷惑。
你的项目和可复用应用
通过前面的教程,我们的工程应该看起来像这样:
- mysite/
- manage.py
- mysite/
- __init__.py
- settings.py
- urls.py
- wsgi.py
- polls/
- __init__.py
- admin.py
- migrations/
- __init__.py
- 0001_initial.py
- models.py
- static/
- polls/
- images/
- background.gif
- style.css
- templates/
- polls/
- detail.html
- index.html
- results.html
- tests.py
- urls.py
- views.py
- templates/
- admin/
- 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 文档中相同的标签名,比如 auth
,admin
,messages
。
将
polls
目录移入django-polls
目录。创建一个名为
django-polls/README.rst
的文件,包含以下内容:
- =====
- Polls
- =====
- Polls is a simple 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 = [
- ...
- 'polls',
- ]
- 2. Include the polls URLconf in your project urls.py like this::
- path('polls/', include('polls.urls')),
- 3. Run `python manage.py migrate` to create the polls models.
- 4. Start the development server and visit http://127.0.0.1:8000/admin/
- to create a poll (you'll need the Admin app enabled).
- 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
包含以下内容:
- import os
- from setuptools import find_packages, setup
- with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as readme:
- README = readme.read()
- # allow setup.py to be run from any path
- os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
- setup(
- name='django-polls',
- version='0.1',
- packages=find_packages(),
- include_package_data=True,
- license='BSD License', # example license
- description='A simple Django app to conduct Web-based polls.',
- long_description=README,
- url='https://www.example.com/',
- author='Your Name',
- author_email='yourname@example.com',
- classifiers=[
- 'Environment :: Web Environment',
- 'Framework :: Django',
- 'Framework :: Django :: X.Y', # replace "X.Y" as appropriate
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: BSD License', # example license
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.5',
- 'Programming Language :: Python :: 3.6',
- 'Topic :: Internet :: WWW/HTTP',
- 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
- ],
- )
- 默认包中只包含 Python 模块和包。为了包含额外文件,我们需要创建一个名为
MANIFEST.in
的文件。上一步中关于 setuptools 的文档详细介绍了这个文件。为了包含模板、README.rst
和我们的LICENSE
文件,创建文件django-polls/MANIFEST.in
包含以下内容:
- include LICENSE
- include README.rst
- recursive-include polls/static *
- recursive-include polls/templates *
- 在应用中包含详细文档是可选的,但我们推荐你这样做。创建一个空目录
django-polls/docs
用于未来编写文档。额外添加一行至django-polls/MANIFEST.in
- recursive-include docs *
注意,现在 docs
目录不会被加入你的应用包,除非你往这个目录加几个文件。许多 Django 应用也提供他们的在线文档通过类似 readthedocs.org 这样的网站。
- 试着构建你自己的应用包通过
ptyhon setup.py sdist
(在django-polls
的目录并构建你自己的应用包,目录内)。这将创建一个名为
distdjango-polls-0.1.tar.gz
。
更多关于打包的信息,见 Python 的 关于打包和发布项目的教程。
使用你自己的包名
由于我们把 polls
目录移出了项目,所以它无法工作了。我们现在要通过安装我们的新 django-polls
应用来修复这个问题。
作为用户库安装
以下步骤将 django-polls
以用户库的形式安装。与安装整个系统的软件包相比,用户安装具有许多优点,例如可在没有管理员访问权的系统上使用,以及防止应用包影响系统服务和其他用户。
注意,用户安装仍然会影响以这个用户身份运行的系统工具,所以 virtualenv
是一个更强大的解决方案(如下所示)。
- 为了安装这个包,使用 pip (你早已 安装 pip, 对吗?):
- pip install --user django-polls/dist/django-polls-0.1.tar.gz
幸运的话,你的 Django 项目应该再一次正确运行。启动服务器确认这一点。
通过 pip 卸载包:
- pip uninstall django-polls
发布你的应用
现在,你已经对 django-polls
完成了打包和测试,准备好向世界分享它!如果这不是一个例子应用,你现在就可以这样做。
- 通过邮件将你的包发送给朋友。
- 将这个包上传至你的网站。
- 将你的包发布至公共仓库,比如 the Python Package Index (PyPI)。 packaging.python.org 有一个不错的 教程 说明如何发布至公共仓库。
通过 virtualenv 安装 Python 包
早些时候,我们以用户库的形式安装了投票应用。这样做有一些缺点。
- 修改用户库会影响你系统上的其他 Python 软件。
- 你将不能运行此包的多个版本(或者其它用有相同包名的包)。一般来说,这些状况只在你同时运行多个 Django 项目时出现。当这个问题出现时,最好的解决办法是使用 virtualenv。这个工具允许你同时运行多个相互独立的Python环境,每个环境都有各自库和应用包命名空间的拷贝。