# 高級教程:如何編寫可重用的應用 #
本高級教程上接教程 6。我們將把我們的網頁投票轉換成一個獨立的Python包,這樣你可以在其它項目中重用或者分享給其它人。
如果你最近沒有完成教程1–6,我們建議你閱讀它們使得你的示例項目與下面描述的相匹配。
## 可重用很重要 ##
設計、構建、測試和維護一個網頁應用有許多工作要做。許多Python 和 Django 項目都有常見的共同問題。如果我們可以節省一些這些重復的工作會不會很棒?
可重用性是Python 中一種生活的態度。Python包索引 (PyPI) 具有廣泛的包,你可以在你自己的Python程序中使用。調查一下Django Packages中已經存在的可重用的應用,你可以結合它們到你的項目。Django 自身也只是一個Python 包。這意味著你可以獲取已經存在的Python包和Django應用并將它們融合到你自己的網頁項目。你只需要編寫你項目的獨特的部分。
比如說,你正在開始一個新的項目,需要一個像我們正在編寫的投票應用。你如何讓該應用可重用?幸運的是,你已經在正確的道路上。在教程 3中,我們看到我們可以如何使用include將投票應用從項目級別的URLconf 解耦。在本教程中,我們將更進一步,讓你的應用在新的項目中容易地使用并隨時可以發布給其它人安裝和使用。
> 包?應用?
>
> Python 包 提供的方式是分組相關的Python 代碼以容易地重用。一個包包含一個或多個Python代碼(也叫做“模塊”)。
>
> 包可以通過import foo.bar 或from foo import bar 導入。如果一個目錄(例如polls)想要形成一個包,它必須包含一個特殊的文件__init__.py,即使這個文件為空。
>
> 一個Django 應用 只是一個Python包,它特意用于Django項目中。一個應用可以使用常見的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
```
你在教程 2中創建了mysite/templates ,在教程 3中創建了polls/templates。 現在你可能更加清晰為什么我們為項目和應用選擇單獨的模板目錄:屬于投票應用的部分全部在polls中。它使得該應用自包含且更加容易丟到一個新的項目中。
現在可以拷貝polls目錄到一個新的Django項目并立即使用。然后它還不能充分準備好到可以立即發布。由于這點,我們需要打包這個應用來讓它對其他人易于安裝。
## 安裝一些前提條件 ##
Python 打包的目前狀態因為有多種工具而混亂不堪。對于本教程,我們打算使用setuptools來構建我們的包。它是推薦的打包工具(已經與distribute 分支合并)。我們還將使用pip來安裝和卸載它。現在你應該安裝這兩個包。如果你需要幫助,你可以參考如何使用pip安裝Django。你可以使用同樣的方法安裝setuptools。
## 打包你的應用 ##
Python packaging refers to preparing your app in a specific format that can be easily installed and used. Django 自己是以非常相似的方式打包起來的。對于一個像polls這樣的小應用,這個過程不是太難。
首先,在你的Django項目之外,為polls創建一個父目錄。稱這個目錄為django-polls。
> 為你的應用選擇一個名字
>
> 讓為你的包選擇一個名字時,檢查一下PyPI中的資源以避免與已經存在的包有名字沖突。當創建一個要發布的包時,在你的模塊名字前面加上django-通常很有用。 這有助于其他正在查找Django應用的人區分你的應用是專門用于Django的。
>
> 應用的標簽(應用的包的點分路徑的最后部分)在INSTALLED_APPS中必須唯一。避免使用與Django的contrib 包 中任何一個使用相同的標簽,例如auth、admin和messages。
將polls 目錄移動到django-polls目錄。
創建一個包含一些內容的文件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::
url(r'^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文件。選擇License超出本教程的范圍,但值得一說的是公開發布的代碼如果沒有License是毫無用處的。Django和許多與Django兼容的應用以BSD License 發布;然而,你可以隨便挑選自己的License。只需要知道你的License的選則將影響誰能夠使用你的代碼。
下一步我們將創建一個setup.py 文件,它提供如何構建和安裝該應用的詳細信息。該文件完整的解釋超出本教程的范圍,setuptools 文檔 有很好的解釋。創建一個文件django-polls/setup.py,其內容如下:
```
django-polls/setup.py
import os
from setuptools import 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=['polls'],
include_package_data=True,
license='BSD License', # example license
description='A simple Django app to conduct Web-based polls.',
long_description=README,
url='http://www.example.com/',
author='Your Name',
author_email='yourname@example.com',
classifiers=[
'Environment :: Web Environment',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License', # example license
'Operating System :: OS Independent',
'Programming Language :: Python',
# Replace these appropriately if you are stuck on Python 2.
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Topic :: Internet :: WWW/HTTP',
'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
],
)
```
默認只有Python模塊和包會包含進包中。如果需要包含額外的文件,我們需要創建一個MANIFEST.in文件。上一步提到的setuptools 文檔對這個文件有更詳細的討論。如果要包含模板、README.rst和我們的LICENSE 文件,創建一個文件django-polls/MANIFEST.in,其內容如下:
```
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這樣的站點提供它們的在線文檔.
試著通過python setup.py sdist 構建你的包(從django-polls的內部運行)。這創建一個dist目錄并構建一個新包django-polls-0.1.tar.gz。
更多關于打包的信息,參見Python 的 打包和分發項目的教程。
## 使用你自己的包 ##
因為,我們將polls 目錄移到項目的目錄之外,它不再工作了。我們將通過安裝我們的新的django-polls包來修復它。
> 安裝成某個用戶的庫
>
> 以下的步驟將安裝django-polls 成某個用戶的庫。根據用戶安裝相比系統范圍的安裝具有許多優點,例如用于沒有管理員權限的系統上以及防止你的包影響系統的服務和機器上的其它用戶。
>
> 注意根據用戶的安裝仍然可以影響以該用戶身份運行的系統工具,所以virtualenv 是更健壯的解決辦法(見下文)。
安裝這個包,使用pip(你已經安裝好它了,對吧?):
```
pip install --user django-polls/dist/django-polls-0.1.tar.gz
```
如果幸運,你的Django 項目現在應該可以再次正確工作。請重新運行服務器以證實這點。
若要卸載這個包,使用pip:
```
pip uninstall django-polls
```
## 發布你的應用: ##
既然我們已經打包并測試過django-polls,是時候與世界共享它了!要不是它僅僅是個例子,你現在可以:
+ 將這個包用郵件發送給朋友。
+ 上傳這個包到你的網站上。
+ 上傳這個包到一個公開的倉庫,例如Python 包索引 (PyPI)。packaging.python.org has a good tutorial for doing this.
## 使用 virtualenv 安裝Python 包 ##
前面,我們將poll 安裝成一個用戶的庫。它有一些缺點:
+ 修改這個用戶的庫可能影響你的系統上的其它Python 軟件。
+ 你將不可以運行這個包的多個版本(或者具有相同名字的其它包)。
特別是一旦你維護幾個Django項目,這些情況就會出現。如果確實出現,最好的解決辦法是使用virtualenv。這個工具允許你維護多個分離的Python環境,每個都具有它自己的庫和包的命名空間。
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[How to write reusable apps](https://docs.djangoproject.com/en/1.8/intro/reusable-apps/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架