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

В продолжение Части 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. В этом уроке мы продвинемся вперёд в решении этого вопроса. А именно, оформим приложение таким образом, чтобы его можно было легко подключать в наших новых проектах. А при желании приложение можно будет опубликовать, и тогда его смогут использовать и другие.

Пакет? Приложение?

Пакет в Python предоставляет способ группировать код Python для последующего повторного использования. Пакет содержит один или несколько файлов с кодом(также известны как “модули”).

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

Приложение (App) в Django является тоже пакетом Python. Только этот пакет адаптирован для использования с Django. Правила Django допускают включение в пакет таких модулей, как models, tests, urls и views.

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

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

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

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

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

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

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

    Выбор название для вашего приложения

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

    Метка приложения (последняя часть пути к пакету приложения) должна быть уникальной в INSTALLED_APPS. Не используйте метки приложений Django из contrib packages, например, auth, admin или messages.

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

  3. Создайте файл 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.
    
  4. Создайте файл django-polls/LICENSE. Выбор лицензии не будет рассматриваться в этом разделе, но помните, что пакет без лицензии бесполезен для сообщества. Django и большое количество Django-приложений распространяются под BSD лицензией, но вы можете выбрать любую другую лицензию.

  5. Теперь создадим файл 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='https://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',
        ],
    )
    
  6. Только модули и пакеты 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 *
    
  7. Не обязательно, но мы рекомендуем, добавлять документацию приложения. Создайте пустой каталог django-polls/docs для будущей документации. Добавьте еще одну строку в django-polls/MANIFEST.in:

    recursive-include docs *
    

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

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

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

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

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

Устанавливаем как библиотеку пользователя

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

Но такая установка влияет на системные приложения запущенные этим пользователем, 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). Это руководство поможет вам.

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

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

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

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

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