Углублённый материал: Как создать повторно применяемое приложение

В продолжение Части 6 мы будем совершенствовать наше приложение Web-poll. Нам предстоит сделать настоящий пакет Python, который можно будет повторно использовать в новых проектах, а главное делиться им с другими разработчиками.

Если вы новичок и все ещё не выполняли занятия с 1 по 6 часть, мы настоятельно рекомендуем сделать это. Весь дальнейший материал опирается на предыдущие главы.

Смысл многократного использования

Большая часть работы уходит на проектирование, сборку, тестирование и конечно же поддержку веб приложения/компонента. У многих Python и Django проектов существуют схожие задачи и проблемы. Вот было бы здорово не повторять однажды проделанную работу, а сохранить её и использовать в будущем. Не правда ли?

Многократное использование - часть философии Python. К примеру, для тех кто ещё не знает что такое The Python Package Index (PyPI) - это громадное хранилище пакетов которые вы можете использовать в собственных Python программах. Посетите Django Packages и вы также увидите много приложений для Django, который были добавлены другими разработчиками. Эти приложения вы можете использовать в собственным проектах - не стесняйтесь, они для того там и есть! По-существу Django сам является обычным Python пакетом. Всё это означает простую истину: вы можете брать любые существующие решения(пакеты, не важно Python или Django) и использовать в своих проектах как угодно. Это даёт большое преимущество в скорости. Не надо придумывать то, что уже придумано другими, а значит можно посвятить всё время только разработке уникальной стороны своего проекта.

Скажем вы начали новый проект в котором используется приложение для голосования, подобно тому, которое мы разрабатывали в предыдущих уроках. Как же сделать наше приложение с голосованием многократно используемым и независимым от проекта к проекту? К счастью, мы уже на правильном пути и затрагивали эту тему в 3 части. Тогда мы уже смогли отделить приложение для голосования от проекта при помощи URLconf, используя include. В этом уроке мы продвинемся вперёд в решении этого вопроса. А именно, оформим приложение таким образом, чтобы его можно было легко подключать в наших новых проектах. А при желании приложение можно будет опубликовать, и тогда его смогут использовать и другие.

Package? App?

Пакет в Python (Package) представляет собой каталог в котором размещается обязательно файл __init__.py и один или несколько “модулей”. А “модуль” - это обычный файл с расширением ‘.py’ в котором размещён код на языке Python.

Пакет может быть импортирован в ваш код так import foo.bar или так from foo import bar. Для того, чтобы обычная директория (к примеру polls) превратилась в пакет, обязательно создайте в этой директории файл __init__.py. Этот файл может быть пустым.

Приложение (App) в Django является тоже пакетом. Только этот пакет адаптирован для использования с Django. Правила Django допускают включение в пакет таких файлов как models.py, forms.py, admin.py и некоторых др.

Позднее мы будем использовать термин packaging для описания процесса создания пакетов для Python.

Ваш проект и ваши приложения

Если вы следовали нашим инструкциям из предыдущих частей урока, ваш каталог проекта должен иметь следующий вид:

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    polls/
        __init__.py
        admin.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 таким образом, чтобы он был автономным. Вот теперь, при желании, этот каталог можно скопировать в наш новый проект. Кроме этого, не забудьте сделать две вещи в новом проекте: добавить название приложения в кортеж INSTALLED_APPS который находится в settings.py, а после этого выполнить в консоли команду ./manage.py syncdb

И хоть приложение сейчас можно переносить из проекта в проект, этого не хватает для того, чтобы делиться с другими. Требуется оформить наше приложение особым образом и запаковать его.

Необходимые условия

Текущее состояние пакетов в Python немного запутано, содержит различные инструменты. В этом учебнике мы будем использовать distribute для создания пакета. Это форк проекта setuptools, созданный сообществом. Для его установки необходим pip. Установите эти два пакета. Доп. информацию можно получить по как установить Django используя pip

Создание пакета с вашим приложением

Пакеты Python созданы для удобного распространения и установки ваших приложений. Django использует аналогичную систему. Для простых приложений, как голосование, это не сложно.

  1. Первым делом создайте родительский каталог для polls вне вашего Django проекта. Назовите его django-polls.

Choosing a name for your app

Выбирая название для вашего пакета, проверьте на PyPI нет ли уже пакета с таким названием. Рекомендуем добавлять префикс django- к названию пакета. Это поможет людям при поиске приложений для Django.

  1. Перенесите каталог polls в django-polls.

  2. Создайте файл 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 syncdb` 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.
    

4. Create a django-polls/LICENSE file. Choosing a license is beyond the scope of this tutorial, but suffice it to say that code released publicly without a license is useless. Django and many Django-compatible apps are distributed under the BSD license; however, you’re free to pick your own license. Just be aware that your licensing choice will affect who is able to use your code.

5. Next we’ll create a setup.py file which provides details about how to build and install the app. A full explanation of this file is beyond the scope of this tutorial, but the distribute docs have a good explanation. Create a file django-polls/setup.py with the following contents:

import os
from setuptools import setup

README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).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',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Topic :: Internet :: WWW/HTTP',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
    ],
)

I thought you said we were going to use distribute?

Distribute - это замена для setuptools. Мы импортируем setuptools, т.к. distribute после установки заменит его.

  1. Только модули и пакеты Python добавляются в пакет по умолчанию. Чтобы добавить другие файлы, необходимо создать файл MANIFEST.in. Документация distribute содержит подробное описание этого файла. Чтобы указать добавление README.rst и LICENSE файлов, создайте django-polls/MANIFEST.in со следующим содержимым:

    include LICENSE
    include README.rst
    recursive-include polls/static *
    recursive-include polls/templates *
    
  2. Не обязательно, но мы рекомендуем, добавлять документацию приложения. Создайте пустой каталог django-polls/docs для будущей документации. Добавьте еще одну строку в django-polls/MANIFEST.in:

    recursive-include docs *
    

    Обратите внимание, каталог docs не будет включен в пакет, пока вы не добавите в него хотя бы один файл. Многие приложения Django также предоставляют документацию онлайн через такие сайты, как readthedocs.org.

  3. Теперь попробуйте собрать ваш пакет выполнив python setup.py sdist (запустите в каталоге django-polls). Эта команда создаст каталог dist и соберет ваш новый пакет, django-polls-0.1.tar.gz.

Подробности о пакетах можно найти в The Hitchhiker’s Guide to Packaging.

Использование ваших пакетов

Т.к. каталог polls был перенесен с каталога проекта, он перестал работать. Исправим это установив пакет django-polls.

Installing as a user library

Инструкция описывает как установить django-polls как библиотеку пользователя. Это лучше, чем устанавливать как системный пакет, таким образом он не влияет на системные сервисы и других пользователей. Python 2.6 добавил поддержку пакетов пользователей, и для старых версий это не сработает, но Django 1.5 требует Python 2.6 и выше.

Но такая установка влияет на системные приложения запущенные этим пользователем, virtualenv более надежный инструмент (смотрите ниже).

  1. Для установки пакета используйте pip (вы уже установили его, правда?):

    pip install --user django-polls/dist/django-polls-0.1.tar.gz
    
  2. Теперь ваш Django проект должен работать. Запустите сервер для проверки.

  3. Для удаления пакета используйте pip:

    pip uninstall django-polls
    

Распространение вашего пакета

Теперь, когда мы создали пакет и проверили его работоспособность, можно поделиться ним с сообществом Django! Если бы это был не просто пример, вы бы могли:

  • Отправить пакет друзьям электронной почтой.

  • Загрузить пакет на ваш сайт.

  • Отправить пакет в публичный репозиторий, такой как The Python Package Index (PyPI).

Подробности о PyPI смотрите на в разделе Quickstart The Hitchhiker’s Guide to Packaging.

Установка пакетов Python с использованием virtualenv

Раньше мы устанавливали пакет как библиотеку пользователя. В этом есть некоторые недостатки:

  • Изменение таких библиотек влияет на другие программы написанные на Python.

  • Вы не сможете использовать разные версии пакета (или пакеты с одинаковым названием).

Обычно такое происходит при работе над несколькими Django проекте. В таком случае лучше всего использовать virtualenv. Этот инструмент позволяет использовать независимые Python окружения, каждое со своими пакетами.