進階教程:如何編寫可重用的應(yīng)用程序
這個進階教程上接 Tutorial 7。 我們將把我們的網(wǎng)頁投票轉(zhuǎn)換成一個獨立的Python包,這樣你可以在其它項目中重用或者分享給其它人。
如果您最近沒有完成教程1-7,我們建議您先看他們,以使您的示例項目與下面描述的項目相匹配。
可重用性很重要
設(shè)計、構(gòu)建、測試和維護一個網(wǎng)頁應(yīng)用有許多工作要做。 許多Python 和 Django 項目都有常見的共同問題。 可重用將會節(jié)省這些重復(fù)性工作。
可重用性在Python 中是一種常見的方式。 Python包索引 (PyPI) 具有廣泛的包,你可以在你自己的Python程序中使用。 查閱一下Django 包 中已經(jīng)存在的可重用的應(yīng)用,你可以結(jié)合它們到你的項目。 Django 自身也只是一個Python 包。 這意味著你可以獲取已經(jīng)存在的Python包和Django應(yīng)用并將它們?nèi)诤系侥阕约旱木W(wǎng)頁項目。 你只需要編寫你項目的獨特的部分。
假設(shè)您正在開始一個新項目,需要一個像我們一直在進行的投票應(yīng)用程序。 你如何讓該應(yīng)用可重用? 幸運的是,你已經(jīng)在正確的道路上。 在 Tutorial 3中,我們看到我們可以如何使用include將投票應(yīng)用從項目級別的URLconf 解耦。 在本教程中,我們將更進一步,讓你的應(yīng)用在新的項目中容易地使用并隨時可以發(fā)布給其它人安裝和使用。
包? 應(yīng)用?
Python 包 按照簡單重用的方式,將具有相關(guān)性的Python代碼歸為一組。 一個包包含一個或多個Python文件(也叫做“模塊”)。
包可以通過import foo.bar或from foo import bar導(dǎo)入。 如果一個目錄(例如polls)想要形成一個包,它必須包含一個特殊的文件__init__.py,即使這個文件為空。
一個Django 應(yīng)用 只是一個Python包,它特意用于Django項目中。 一個應(yīng)用可以使用常見的Django 約定,例如具有urls、tests、models和views子模塊。
后面我們使用打包這個詞來描述將一個Python包變得讓其他人易于安裝的過程。 這可能有點讓人覺得困惑。
您的項目和您的可重用應(yīng)用程序
經(jīng)過前面的教程之后,我們的項目應(yīng)該看上去像這樣:
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
你在 Tutorial 3和 Tutorial 7中創(chuàng)建了polls/templates和mysite/templates。 現(xiàn)在你可能更加清晰為什么我們?yōu)轫椖亢蛻?yīng)用選擇單獨的模板目錄:屬于投票應(yīng)用的部分全部在polls中。 它使得該應(yīng)用“自包含(self-contained)”且更加容易丟到一個新的項目中。
現(xiàn)在可以拷貝polls目錄到一個新的Django項目并立即重用。 盡管它還不能充分準(zhǔn)備好到可以立即發(fā)布。 所以,我們需要打包這個應(yīng)用來讓它對其他人易于安裝。
安裝一些先決條件
Python 打包的目前狀態(tài)因為有多種工具而混亂不堪。 對于本教程,我們打算使用setuptools來構(gòu)建我們的包。 它是推薦的打包工具(已經(jīng)與distribute 分支合并)。 我們還將使用pip來安裝和卸載它。 現(xiàn)在你應(yīng)該安裝這兩個包。 如果你需要幫助,你可以參考 how to install Django with pip。 你可以使用同樣的方法安裝setuptools。
打包您的應(yīng)用程序
Python 打包 會將你的應(yīng)用預(yù)處理成一種特殊的格式, 這樣安裝和使用就會變得簡單。 Django 自己是以非常相似的方式打包起來的。 對于一個像polls這樣的小應(yīng)用,這個過程不是太難。
- 首先,在你的Django項目之外,為polls創(chuàng)建一個父目錄。 稱這個目錄為django-polls。
為你的應(yīng)用選擇一個名字
當(dāng)為你的包選擇一個名字時,檢查一下PyPI中的資源以避免與已經(jīng)存在的包有名字沖突。 當(dāng)創(chuàng)建一個要發(fā)布的包時,在你的模塊名字前面加上django-通常很有用。 這有助于其他正在查找Django應(yīng)用的人區(qū)分你的應(yīng)用是專門用于Django的。
應(yīng)用程序標(biāo)簽(即應(yīng)用程序包的虛線路徑的最后一部分)必須在INSTALLED_APPS中是唯一的。 避免使用與Django的contrib 包 中任何一個使用相同的標(biāo)簽,例如admin、auth和messages。
將polls 目錄移動到django-polls目錄中。
創(chuàng)建一個包含以下內(nèi)容的文件django-polls/README.rst:
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.
創(chuàng)建一個django-polls/LICENSE文件。 如何選擇License超出本教程的范圍,但值得一說的是, 公開發(fā)布的代碼如果沒有License是毫無用處的。 Django和許多Django兼容的應(yīng)用程序是根據(jù)BSD許可證分發(fā)的;但是,您可以自由選擇自己的許可證。 只需知道你所選擇的License,將決定誰能使用你的代碼.
下一步我們將創(chuàng)建一個
setup.py文件,它提供如何構(gòu)建和安裝該應(yīng)用的詳細(xì)信息。 該文件完整的解釋超出本教程的范圍,setuptools 文檔 有很好的解釋。 創(chuàng)建一個文件django-polls/setup.py,其內(nèi)容如下:
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',
],
)
- 默認(rèn)只有Python模塊和包會包含進包中。 如果需要包含額外的文件,我們需要創(chuàng)建一個MANIFEST.in文件。 上一步提到的setuptools 文檔對這個文件有更詳細(xì)的討論。 如果要包含模板、
django-polls/MANIFEST.in和我們的LICENSE 文件,創(chuàng)建一個文件README.rst,其內(nèi)容如下:
django-polls/MANIFEST.in
include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates *
- 這是可選的,但建議您在應(yīng)用程序中包含詳細(xì)的文檔。 創(chuàng)建一個空目錄django-polls/docs以供將來使用。 向django-polls/MANIFEST.in添加另外一行:
recursive-include docs *
注意docs不會包含進你的包中除非你添加一些文件到它下面。 許多Django應(yīng)用還通過類似readthedocs.org這樣的站點提供它們的在線文檔.
- 試著通過python setup.py sdist 構(gòu)建你的包(從django-polls的內(nèi)部運行)。 這會創(chuàng)建一個django-polls-0.1.tar.gz目錄并構(gòu)建一個新包:dist。
更多關(guān)于打包的信息,參見Python 的 打包和分發(fā)項目的教程。
使用你自己的包
因為,我們將polls 目錄移到項目的目錄之外,它不再工作了。 我們將通過安裝我們的新的django-polls包來修復(fù)它。
安裝成某個用戶的庫
以下的步驟將安裝django-polls成某個用戶的庫。 用戶級別的安裝比系統(tǒng)級別的安裝有許多優(yōu)點,例如將包運行在普通用戶級別上不但不會影響系統(tǒng)服務(wù)還不會影響其他用戶
注意根據(jù)用戶的安裝仍然可以影響以該用戶身份運行的系統(tǒng)工具,所以virtualenv是更健壯的解決辦法(見下文)。
- 要安裝軟件包,請使用pip(您已經(jīng)installed it,對吧?):
pip install --user django-polls/dist/django-polls-0.1.tar.gz
幸運的話,你的Django 項目現(xiàn)在應(yīng)該又能正常工作了。 請重新運行服務(wù)器以證實這點。
若要卸載這個包,使用pip:
pip uninstall django-polls
發(fā)布您的應(yīng)用程序
既然我們已經(jīng)打包并測試過django-polls,是時候與世界共享它了! 如果它不僅僅是個例子,你現(xiàn)在可以:
- 將這個包用郵件發(fā)送給朋友。
- 在您的網(wǎng)站上上傳包。
- 上傳這個包到一個公開的倉庫,例如Python 包索引 (PyPI)。 packaging.python.org 上面有 很好的教程 講述具體流程。
使用 virtualenv 安裝Python包
前面,我們將poll 安裝成一個用戶的庫。 它有一些缺點:
- 修改這個用戶的庫可能影響你的系統(tǒng)上的其它Python 軟件。
- 你將不可以運行這個包的多個版本(或者具有相同名字的其它包)。
特別是一旦你維護幾個Django項目,這些情況就會出現(xiàn)。 如果確實出現(xiàn),最好的解決辦法是使用virtualenv。 這個工具允許你維護多個分離的Python環(huán)境,每個都具有它自己的庫和包的命名空間。