Автоматическая установка Django (APS-пакет). Компактный сервер для Django приложений

pip install Django==2.1.7

Option 2: Get the release candidate for 2.2

pip install --pre django

Option 3: Get the latest development version

The latest and greatest Django version is the one that’s in our Git repository (our revision-control system). This is only for experienced users who want to try incoming changes and help identify bugs before an official release. Get it using this shell command, which requires Git :

git clone https://github.com/django/django.git

Additional information

For the impatient:

  • Latest release:
    Checksums:
    Release notes:
  • Preview release:
    Checksums:
    Release notes:

Which version is better?

We improve Django almost every day and are pretty good about keeping the code stable. Thus, using the latest development code is a safe and easy way to get access to new features as they’re added. If you choose to follow the development version, keep in mind that there will occasionally be backwards-incompatible changes. You’ll want to pay close attention to the commits by watching Django on GitHub or subscribing to django-updates .

If you’re just looking for a stable deployment target and don’t mind waiting for the next release, you’ll want to stick with the latest official release (which will always include detailed notes on any changes you’ll need to make while upgrading).

Previous releases

  • Django 2.0.13:
    Checksums:
    Release notes:
  • Django 1.11.20 (LTS):
    Checksums:
    Release notes:

Данная заметка это продолжение статьи про написание telegram бота , в ней я постараюсь максимально подробно осветить тему разворачивания (deploy) полноценного, хотя и маленького, Django приложения в production среде на ОС Linux, Ubuntu 14.04 LTS. К концу статьи у нас будет полноценный telegram бот, крутящийся в вебе и принимающий команды от пользователей этого мессенджера.

Чему вы научитесь после прочтения заметки:

  • Разворачивать Django приложение (да и любое WSGI приложение) на хостинге Digital Ocean в среде Linux
  • Работать с веб-серверами nginx и gunicorn
  • Управлять процессами, используя утилиту supervisord
  • Настраивать virtualenv с помощью pyenv
  • Автоматически запускать веб-приложение даже после перезагрузки сервера

В сентябре 2015 года мы проводили Python митап в Алматы на котором я выступал с . Во время выступления я вкратце описал веб эко-систему Python и сделал краткий обзор популярного инструментария. К сожалению, формат митапа не предусматривал детальный разбор темы, поэтому новичкам в этой области обычно приходится дальше копаться самостоятельно. Сегодня я постараюсь восполнить этот пробел и немного углубиться в "горячую" тему деплоя веб приложений на Python. Несмотря на то, что в статье речь будет идти о Django приложении, описываемые рецепты будут актуальны и для других веб-проектов, разработанных на Python с использованием WSGI-совместимых фреймворков (Flask, Bottle, Pyramid, Falcon, web2py и так далее).

В заметке я буду делать деплой на виртуальном хостинге от Digital Ocean. Если вы зарегистрируетесь по этой ссылке , то после подтверждения платёжных данных, счёт вашего аккаунта сразу пополнится на $10, которые можно потратить на создание маленьких дроплетов (виртуальных серверов) и потренироваться в разворачивании веб проектов на Python. Сразу скажу, что вам необязательно всё делать на удалённой машине и вообще использовать хостинг-провайдер, можно обойтись и локальной виртуалкой, например, используя VirtualBox и (но в таком случае невозможно будет установить webhook).

Создание виртуального сервера

Как я ранее уже упоминал, деплой мы будет производить на одном из виртуальных серверов DigitalOcean с его мощным API:)

Создаём дроплет, нажимая на "Create droplet" в правом верхнем углу панели управления:

Выбираем самый минимальный тариф за 5 долларов в месяц с операционной системой Ubuntu 14.04.4 LTS на борту будущей виртуальной машины.

В качестве дата-центра я практически всегда выбираю Frankfurt, так как до него у меня самый лучший пинг. После заполнения всех необходимых полей, нажимаем кнопку "Create". Дроплет создаётся в течение 60 секунд после которых на почту поступает вся необходимая для доступа информация о новой виртуальной машине: IP адрес, логин и пароль.

Настройка сервера

Обновляем пакеты:

# apt-get update # apt-get -y upgrade

# adduser django # adduser django sudo

Заходим под новым юзером django на сервер, и все остальные команды выполняем из под данного юзера.
Устанавливаем необходимый арсенал для настройки виртуального окружения через Pyenv и сборки самой последней версии Python (2.7.11).

$ sudo apt-get install -y build-essential $ sudo apt-get install -y python-dev libreadline-dev libbz2-dev libssl-dev libsqlite3-dev libxslt1-dev libxml2-dev $ sudo apt-get install -y git

После этого ставим сам Pyenv. Подробнее о том что такое Pyenv и как его настроить можно прочитать :
Устанавливаем Python самой последней версии (Python 2.7.11):

$ pyenv install 2.7.11 Downloading Python-2.7.11.tgz... -> https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz Installing Python-2.7.11... Installed Python-2.7.11 to /home/django/.pyenv/versions/2.7.11

Выполнение команды займёт некоторое время (скрипт скачает Python и скомпилирует его из исходников). Устанавливая отдельный интерпретатор питона мы тем самым никак не влияем на работу системного, более того, в последней LTS версии Ubuntu (14.04) используется версия 2.7.6, в которой существует ряд серьёзных уязвимостей, включая баг с SSL, а также отсутствует поддержка TLS 1.2

Клонируем репозиторий с Django проектом:

$ cd ~ $ git clone https://github.com/adilkhash/planetpython_telegrambot.git $ cd planetpython_telegrambot/

$ pyenv virtualenv 2.7.11 telegram_bot $ pyenv local telegram_bot

Ставим зависимости через менеджер пакетов pip.

Pip install -r requirements.txt

Django приложение, написанное в первой части, претерпело незначительные изменения. В частности я перенёс изменяемые части кода в специальный.env файл, используя библиотеку django-environ. Ознакомиться с изменениями можно по этой ссылке .

Создаём.env файл из шаблона и заполняем необходимые настройки.

$ cd blog_telegram && mv .env-template .env && vi .env

В частности необходимо изменить режим DEBUG на False, прописать токен для Telegram бота и указать дополнительный хост через запятую в ALLOWED_HOSTS. В моём случае ALLOWED_HOSTS выглядит вот так:

ALLOWED_HOSTS=127.0.0.1,bot.сайт

То есть я завёл дополнительный поддомен на котором и будет крутиться Telegram бот.

Настройка SSL сертификата

В прошлой статье я писал о том, что в случае использования API вызова setWehook, хосту необходимо иметь валидный SSL сертификатом (Telegram позволяет использовать также самоподписанные сертификаты). Сертификат мы будет создавать через бесплатный сервис выдачи SSL сертификатов Let"s Encrypt .

$ cd ~ && git clone https://github.com/letsencrypt/letsencrypt $ cd letsencrypt/ $ ./letsencrypt-auto certonly --standalone -d bot.сайт

Необходимо будет указать некоторые настройки и согласиться с условиями предоставления услуг. После успешного выполнения команд, сертификаты будут находиться в /etc/letsencrypt/live/bot.сайт/

Настройка Nginx

Теперь пора поставить популярный HTTP сервер nginx который в нашем случае будет выполнять роль проксирующего (принимать запросы от клиентов и передать их дальше следуя инструкциям в конфигурационном файле).

$ sudo apt-get install -y nginx $ cd /etc/nginx/sites-available/ $ sudo nano telegram_bot.conf

Заполняем новый файл telegram_bot.conf следующим содержимым:

Server { listen 80; listen 443 ssl; server_name bot..сайт/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/bot..pem; location / { proxy_set_header Host $http_host; proxy_redirect off; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Scheme $scheme; proxy_pass http://localhost:8001/; } }

ВНИМАНИЕ : Не забудьте заменить хост bot.сайт на свой собственный.

Прописываем наш новый конфиг в настройки nginx и перезагружаем его, чтобы изменения вступили в силу:

$ cd /etc/nginx/sites-enabled/ $ sudo ln -s ../sites-available/telegram_bot.conf telegram_bot.conf $ sudo service nginx restart

Что мы только что сделали?

  • Прописали валидный SSL серификат для нашего сайта
  • Все запросы, поступающие на хост, будут проксироваться на наше будущее Django приложение, которое в свою очередь, должно крутиться на 8001 порту.
  • Передаём дополнительные HTTP заголовки в каждом запросе (хост, IP адрес клиента, схему https/http и так далее). Более подробно про настройки nginx можно прочитать .

Чтобы проверить успешность наших настроек, можно запустить django приложение через тестовый сервер командой runserver на 8001 порту и зайти на сайт:

$ cd ~/planetpython_telegrambot/ $ python manage.py runserver 8001

Открываем браузер и видим (я сразу открыл через https):

URL Not Found это нормальное явление, так как у нас задан всего 1 валидный URL для непосредственной работы с Telegram - /planet/bot// (не считая настройки Django админки).

Настройка Gunicorn через Supervisor

Пора приступить к настройке production-ready HTTP сервера Gunicorn , который, кстати, полностью написан на языке Python и хорошо зарекомендовал себя в реальном бою (к слову, во всех "живых" проектах я использую именно эту связку: nginx+gunicorn)

Что такое Supervisor?

Supervisor это утилита процесс-менеджер. Она "следит за здоровьем" ваших процессов-демонов и в случае их падения, старается снова их поднять. Если в ходе работы Gunicorn "падает" (системная ошибка, не та фаза луны и так далее), Supervisor старается его снова "поднять", таким образом работоспособность сайта не страдает. К слову, у меня в планах есть идея написать небольшую заметку про эту утилиту, так сказать Supervisor Advanced Usage. Стоит отметить, что все процессы, запущенные в Supervisor должны работать в foreground режиме, чтобы утилита понимала когда что-то идёт не по плану.

Для начала составим конфигурационный файл для запуска Gunicorn внутри Supervisor. Его содержимое выглядит вот так:

Command=/home/django/.pyenv/versions/telegram_bot/bin/gunicorn blog_telegram.wsgi:application -b 127.0.0.1:8001 -w 1 --timeout=60 --graceful-timeout=60 --max-requests=1024 directory=/home/django/planetpython_telegrambot/ user=django redirect_stderr=True stdout_logfile=/tmp/gunicorn.log stderr_logfile=/tmp/gunicorn_err.log autostart=true autorestart=true startsecs=10 stopwaitsecs=10 priority=999

Сохраняем файл под именем gunicorn.conf (~/planetpython_telegrambot/gunicorn.conf ). К слову, Gunicorn прописан в зависимостях нашего проекта (requirements.txt ) и так как мы его уже установили в наше окружение, то узнать путь исполняемого файла можно выполнив команду внутри активированного виртуального окружения (активация происходит автоматически при переходе в директорию веб-приложения из-за наличия там файла .python-version , созданного через pyenv local):

$ pyenv which gunicorn

Содержимое конфигурационного файла для supervisord:

File=/tmp/telgram_bot_supervisord.sock logfile=/tmp/telgram_bot_supervisord.log logfile_maxbytes=50MB logfile_backups=10 loglevel=info pidfile=/tmp/telgram_bot_supervisord.pid nodaemon=false minfds=1024 minprocs=200 supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface serverurl=unix:///tmp/telgram_bot_supervisord.sock files = /home/django/planetpython_telegrambot/gunicorn.conf

Сохраняем в ~/planetpython_telegrambot/supervisord.conf

$ supervisord

Запуск должен пройти без каких либо ошибок. Чтобы узнать статус текущих процессов, запускаем утилиту supervisorctl:

$ supervisorctl gunicorn RUNNING pid 20901, uptime 0:04:18 supervisor>

Для получения помощи, можно выполнить команду help. А для получения информации о команде - help . Например:

Supervisor> help stop stop Stop a process stop:* Stop all processes in a group stop Stop multiple processes or groups stop all Stop all processes supervisor>

После успешного запуска supervisor, сайт должен быть доступен онлайн.

Автозапуск веб-приложения при перезагрузке

А что будет, если наш виртуальный сервер внезапно перезагрузится? (сбой в дата-центре, неполадки на хост машине, криворукий админ накосячил и т.д.). В случае такого сценария, сейчас наше приложение не будет запущено автоматически. Чтобы это исправить необходимо приложить ещё немного усилий дабы написать небольшой скрипт, который мы успешно поместим в механизм автозагрузки ОС Ubuntu (Debian-like дистрибутивов).

Доводилось ли вам слышать про так называемые upstart файлы? Именно написанием одного из них мы сейчас и займёмся. К слову, на текущий момент Upstart признана устаревшей и в новых версиях ОС на базе Linux планируется полный переход на systemd.

Description "Supervisor Telegram bot django app starting handler" start on runlevel stop on runlevel [!2345] respawn setuid django setgid django chdir /home/django/planetpython_telegrambot/ exec /home/django/.pyenv/versions/telegram_bot/bin/supervisord

Файл должен быть помещён в /etc/init/ (в моём случае я дал ему имя telegram_bot.conf). Если ранее все запуски не вызывали проблем, то после рестарта системы, приложение автоматически будет запущено:

$ sudo shutdown -r now

Теперь необходимо прописать наш URL на стороне Telegram используя вызов API метода setWebhook:

Import telepot bot_token = "BOT_TOKEN" bot = telepot.Bot(bot_token) bot.setWebhook("https://bot..format(bot_token=bot_token))

На этом настройка бота закончена. Посылаем команды нашему боту @PythonPlanetBot и получаем адекватные ответы:)

  • логирование запросов от пользователей в файл
  • вынес изменяемые настройки (режим debug, токен бота, секретный ключ) в переменные окружения через.env файлы, используя django-environ
  • добавил шаблоны конфигурационных файлов для gunicorn, nginx и supervisor

Django – это мощный фреймворк для создания приложений Python. Такой полнофункциональный фреймворк, как Django, значительно ускоряет процесс создания и развёртывания приложения, беря на себя общее структурирование кода; таким образом, разработчик может сосредоточиться на уникальности и контенте сайта.

В данном руководстве рассматриваются различные методы установки Django на сервер Ubuntu 14.04, а также начало работы с этим фреймворком.

Методы установки Django

Существует несколько различных методов установки Django, каждый из которых имеет свои преимущества в определённых ситуациях.

  • Глобальная установка Django из пакета. Официальный репозиторий Ubuntu предоставляет пакеты Django, которые можно без труда установить при помощи менеджера пакетов apt. Этот метод очень прост, но не так гибок, как другие методы. Кроме того, репозиторий может содержать несколько устаревшую версию пакета Django.
  • Глобальная установка Django при помощи pip. Инструмент pip – это менеджер пакетов Python. С его помощью можно выполнить общесистемную установку Django. Он, как правило, предоставляет последнюю доступную версию пакета. Однако глобальные (общесистемные) установки всегда менее гибки.
  • Установка через pip в Virtualenv. Пакет virtualenv позволяет создавать автономные окружения для разных проектов. При помощи этой технологии можно установить Django в каталог проекта, при этом не повлияв на систему в целом. Это позволяет задавать индивидуальные настройки для каждого проекта. Виртуальное окружение (или среда) – гораздо более гибкий вариант установки пакета.
  • Установка разрабатываемой версии через Git. Чтобы установить последнюю разрабатываемую версию вместо стабильного релиза, нужно получить код из репозитория git . Это предоставит новейшие функции и исправления программы; установить такую версию можно как глобально, так и локально. Но имейте в виду: разрабатываемые версии нестабильны.

Выберите наиболее подходящий вариант установки Django и следуйте инструкциям соответствующего раздела данной статьи.

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

Процесс установки Django из официального репозитория Ubuntu очень прост. Для начала нужно обновить список локальных пакетов при помощи apt, а затем установить пакет python-django.

sudo apt-get update
sudo apt-get install python-django

Чтобы убедиться, что установка прошла успешно, запросите версию программы.

django-admin --version
1.6.1

Появившийся номер версии значит, что установка прошла успешно.

Обратите внимание : Эта версия не является последней доступной версией Django.

Глобальная установка через pip

Чтобы глобально установить последнюю стабильную версию Django, используйте инструмент pip, менеджер пакетов Python. Чтобы установить pip, нужно сначала обновить список пакетов:

sudo apt-get update

Чтобы установить pip для Python 2, введите:

Чтобы установить pip для Python 3, используйте:

Теперь менеджер пакетов pip установлен, можно приступать к установке Django. Для Python 2 введите:

sudo pip install django

Для Python 3 наберите:

sudo pip3 install django

Чтобы убедиться, что установка прошла должным образом, введите:

django-admin --version
1.7.5

Как видите, pip предоставляет более новый релиз Django, чем репозиторий Ubuntu.

Установка Django через pip в Virtualenv

Вероятно, наиболее гибким вариантом установки является использование virtualenv. Этот инструмент позволяет создавать виртуальные окружения Python, в которые можно устанавливать любые необходимые пакеты, не влияя на систему в целом. Благодаря virtualenv можно выбирать пакеты для проектов на индивидуальной основе и при этом не беспокоиться о конфликте зависимостей.

Дл начала нужно установить менеджер pip из официального репозитория Ubuntu. Обновите список пакетов:

sudo apt-get update

Для Python 2:

sudo apt-get install python-pip

Для Python 3:

sudo apt-get install python3-pip

После установки pip его можно использовать для установки пакета virtualenv.

Для Python 2 введите:

sudo pip install virtualenv

Для Python 3:

sudo pip3 install virtualenv

Теперь можно создать индивидуальную виртуальную среду для любого проекта. Создайте каталог нового проекта и перейдите в него:

mkdir ~/newproject
cd ~/newproject

Создайте виртуальное окружение в каталоге проекта:

virtualenv newenv

Примечание : Замените условное название newenv своим названием.

Эта команда создаст автономную среду, установит Python и pip в изолированный каталог. Созданный каталог будет содержать файловую иерархию для установки пакетов.

Чтобы установить пакеты в изолированную среду, включите её:

source newenv/bin/activate

После этого командная строка изменится, что говорит о том, что виртуальная среда была включена. Она будет выглядеть примерно так:

(newenv)username@hostname:~/newproject$.

В новом окружении используйте pip для установки Django. Вне зависимости от того, какую версию Python вы используете, в виртуальной среде нужно запускать только команду pip. Кроме того, при локальной установке не нужно использовать sudo.

pip install django

Убедитесь, что программа установлена успешно.

django-admin --version
1.7.5

Чтобы покинуть виртуальную среду, используйте команду:

После этого командная строка примет свой стандартный вид. Чтобы снова включить виртуальную среду, вернитесь в каталог проекта и введите:

cd ~/newproject
source newenv/bin/activate

Установка разрабатываемой версии Django из git

Чтобы установить разрабатываемую версию Django, загрузите её из репозитория git.

Для этого установите git при помощи стандартного менеджера пакетов apt. Обновите список пакетов:

sudo apt-get update

А затем установите git и менеджер пакетов pip, который понадобится позже для установки Django. Для Python 2 используйте:

sudo apt-get install git python-pip

Для Python 3:

sudo apt-get install git python3-pip

После установки git клонируйте репозиторий Django. Он содержит новейшие функции и исправления, но не является стабильным. Чтобы клонировать репозиторий в каталог django-dev в домашнем каталоге, введите:

git clone git://github.com/django/django ~/django-dev

После этого установите его при помощи pip. Используйте флаг -e для установки в режиме editable, поскольку это необходимо при установке через систему контроля версий. Для Python 2:

sudo pip install -e ~/django-dev

Для Python 3:

sudo pip3 install -e ~/django-dev

Введите следующую команду, чтобы убедиться, что установка прошла успешно:

django-admin --version
1.9.dev20150305171756

Примечание : Этот метод можно применить в виртуальной среде и таким образом изолировать нестабильную версию Django.

Создание проекта Django

После установки Django ознакомьтесь с основами использования этого фреймворка.

Для создания проекта используется команда django-admin:

django-admin startproject projectname
cd projectname

Эта команда создаст каталог projectname в текущем каталоге и поместит в него скрипт управления и другой каталог по имени projectname с текущим кодом.

Примечание : Находясь в каталоге проекта, созданном при помощи virtualenv, Django может разместить скрипты управления и внутренние каталоги в текущем каталоге при помощи следующей команды (обратите внимание на точку в конце стоки):

django-admin startproject projectname .

Чтобы сгенерировать базу данных в более новых версиях Django (по умолчанию используется SQLite), введите:

python manage.py migrate

Если команда migrate не работает, значит, текущая версия Django является более старой и не поддерживает её. В таком случае используйте:

python manage.py syncdb

При этом Django попросит создать учётную запись администратора; укажите имя пользователя, электронный адрес и пароль.

При использовании команды migrate нужно создать учётную запись администратора вручную. Для этого наберите:

python manage.py createsuperuser

Программа также запросит имя пользователя, адрес электронной почты и пароль.

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

python manage.py runserver 0.0.0.0:8000

В браузере посетите IP-адрес, задав порт:

server_ip_address:8000

Это откроет приветственную страницу Django.

server_ip_address:8000/admin

Введите имя и пароль администратора, чтобы получить доступ к панели управления.

Ознакомившись со стандартным проектом, остановите сервер разработки, введя в терминал CTRL-C. Этот стандартный проект Django является структурной основой для разработки уникального сайта. Чтобы узнать, как создавать пользовательские приложения и настроить свой сайт, читайте документацию Django.

Итоги

Итак, теперь на сервер установлен мощный фреймворк Django, обеспечивающий вас всеми необходимыми инструментами для разработки веб-приложений. Полноценный фреймворк Django способен значительно ускорить процесс разработки, позволяя вам сосредоточиться на уникальности приложения.

Tags: ,

Какая оптимальная структура для ваших Django приложений, настроек и других ассоциированных директорий?

Когда вышла Django 1.4 она включала обновленую структуру проекта, которая прошла долгий путь, чтобы стать основной, но здесь, собраны некоторые улучшения, чтобы сделать структуру лучше.

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

Почему данная структура лучше

  1. Позволяет вам держать, пересобирать и переисопльзовать индивидальные Django приложения для использования в других проектах. Ведь не всегда создаваемое приложение делается реиспользуемым, но в будущем, может вырасти в такое. Построение проекта описываемым способом, позволяет писать реиспользуемые приложения сразу же, а не только, когда потребуется.
  2. Поощряет разработку реиспользуемых приложений
  3. Индивидуальных настройки для каждого окружения. Никаких больше “if DEBUG ==True” в едином монолитном файле настроек. Это позволяет легко видеть, какие настройки общие и что переопределяется на каждом окружении.
  4. Индивидульный список pip зависимостей для каждого окружения.
  5. Шаблоны проекта и статические файлы, если требуется, могут переопределять значения по умолчанию уровня приложений.
  6. Небольшие более детальные тестовые файлы, которые легче для чтения и понимания.

Предположим, у вас есть 2 приложения blog и users и 2 окружения dev и prod , значит, ваш проект должен иметь следующий вид:

myproject/ manage.py myproject/ __init__.py urls.py wsgi.py settings/ __init__.py base.py dev.py prod.py blog/ __init__.py models.py managers.py views.py urls.py templates/ blog/ base.html list.html detail.html static/ … tests/ __init__.py test_models.py test_managers.py test_views.py users/ __init__.py models.py views.py urls.py templates/ users/ base.html list.html detail.html static/ … tests/ __init__.py test_models.py test_views.py static/ css/ … js/ … templates/ base.html index.html requirements/ base.txt dev.txt test.txt prod.txt

Продолжение этой статьи расскажет, как привести свой проект к такой структуре и почему она лучше.

Текущая структура по умолчанию

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

Если вы запустите свой проект с помощью команды django-admin.py startproject foo , вы получите следующую структуру:

foo/ manage.py foo/ __init__.py settings.py urls.py wsgi.py

Эта схема очень хороша для старта. У нас есть корневая директория foo , которая содержит наш manage.py и директорию проекта foo/foo . Эту директорию можно добавить в свою систему контроля версия, например в git.

Вы можете подумать, что директория foo/foo начало проекта, где все кроме этого это Django приложения или вспомогательные файлы относящиеся к проекту.

Исправляем настройки

Наша первая миссия, это исправить ваш плохой файл настроек. Мы показали данную архитектуру нашим клиентам и были впечатлены, как мало людей знают, что такое можно реализовать. Я виню в этом тот факт, что каждый знает, что файл настроек это просто Python код, но они не думают о нем, как о Python коде.

И так, давайте исправим наши настройки. Для нашего проекта foo реализуем схему с 4 окружениями: dev, stage, jenkins, и production. Давайте дадим каждому окружения свой собственный файл. Процесс для этого следующий:

  1. В foo/foo создадим директорию settings и пустой файл __init__.py внутри нее.
  2. Перенесем foo/foo/settings.py в foo/foo/settings/base.py
  3. Создадим индивидуальные файлы dev.py , stage.py , jenkins.py , и production.py в foo/foo/settings/ . Каждый из этих файлов должен содержать следующее

from base import *

Так, почему это важно? Для локальной разработки вам требуется DEBUG =True , но вы также, можете случайно выкатить это и в продакшен, поэтому просто откройте foo/foo/settings/production.py и после первой строки импорта вставьте DEBUG =False . Теперь, ваш продакшен сайт защищен от такой случайности.

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

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

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

export DJANGO_SETTINGS_MODULE = “foo.settings.jenkins”

И бум, вы теперь используете jenkins настройки.

Или вы можете предпочесть передачу настроек через коммандную строку:

./manage.py migrate -settings= foo.settings.production

Или используя gunicorn:

gunicorn -w 4 -b 127.0.0.1:8001 -settings= foo.settings.dev

Что еще должно быть настроено?

Другая часто используемая уловка с Django настройками, это изменить тип некоторых настроек с tuple на list. Для примера, INSTALLED_APPS изменить с:

INSTALLED_APPS = ( … )

INSTALLED_APPS = [ … ]

В foo/settings/base.py мы теперь можем проще добавлять и удалять приложения основываясь на конкретном файле настроек для текущего окружения. Для примера, возможно вам требуется модуль django-debug-toolbar установленным только в dev окружении.

Этот трюк также часто используется с настройками TEMPLATE_DIRS и MIDDLEWARE_CLASSES .

Еще один часто используемый трюк, это разбить ваши приложения на 2 списка, первый это глобальные зависимости, второй - специфичные для данного проекта. Как, например, здесь:

PREREQ_APPS = [ ‘ django . contrib . auth ’ , ‘ django . contrib . contenttypes ’ , … ‘ debug_toolbar ’ , ‘ imagekit ’ , ‘ haystack ’ , ] PROJECT_APPS = [ ‘ homepage ’ , ‘ users ’ , ‘ blog ’ , ] INSTALLED_APPS = PREREQ_APPS + PROJECT_APPS

Почему это часто используется? Во первых, это помогает лучше различать Django core компоненты, сторонние приложения и внутренние, специфичные для данного проекта. Тем не менее, PROJECT_APPS часто управляет списком специфичных пакетов, для вещей таких как: тестирование и покрытие кода тестами. Вы имеет список с вашими приложениями, поэтому можете легко и автоматизированно убедиться, что все тесты были запущены только для них, а не для каких-то посторонних модулей.

Исправляем зависимости

Большинство проектов содержат лишь один файл requirements.txt , который ставит зависимости примерно так:

pip install -r requirements.txt

Этого достаточно для маленьких проектов, но малоизвестная возможность requirements файлов это использование ключа -f для включения других файлов:

R base.txt pytest == 2.5.2 coverage == 3.7.1

Я признаю, что это не огромная выгода, но это позволяет разделить зависимости на каждое окружение. Но для успокоения совести скажу, что это позволяет увеличить скорость установки пакетов, ведь вам не требуется стаивть на продакшен инсталяции пакеты, которые не будут использоваться.

Тестовые файлы

Почему мы разделяем тесты так сильно? Главная причина, если вы пишете достаточное количество тестов в одном файле tests.py для каждого приложения, то в конце концов он станет огромным и не поддерживаемым. Это плохо для читабельности, но также это простой факт, что вы тратите много времени на пролистывание текста.

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

Ссылки (URLs)

Для маленьких проектов заманчиво определять все ссылки в одном файле foo/urls.py для сохранения их в одном месте. Как бы то ни было, если ваша цель это ясность и реиспользование, вы должны определять ссылки в каждом приложении и загружать их в корневом файле. Вместо:

urlpatterns = patterns (‘’ , url (r ’ ^ $’ , HomePageView . as_view (), name = ‘ home ’ ), url (r ’ ^ blog / $’ , BlogList . as_view (), name = ‘ blog_list ’ ), url (r ’ ^ blog / (? P < pk > \d + ) / $’ , BlogDetail . as_view (), name = ‘ blog_detail ’ ), … url (r ’ ^ user / list / $’ , UserList . as_view (), name = ‘ user_list ’ ), url (r ’ ^ user / (? P < username > \w + ) / $’ , UserDetail . as_view (), name = ‘ user_detail ’ ), )

вы должны использовать:

urlpatterns = patterns (‘’ , url (r ’ ^ $’ , HomePageView . as_view (), name = ‘ home ’ ), url (r ’ ^ blog / ‘ , include (‘ blog . urls ’ )), url (r ’ ^ user / ‘ , include (‘ user . urls ’ )), )

Шаблоны и статические файлы

Использование templates/ и static/ директорий на каждое приложение дает способность к реиспользованию этого приложения в другом проекте как есть, без изменений.

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

Также, это дает нам возможность переопределить шаблоны на каждый проект базируясь на директории foo/templates/ . При добавлении шаблона templates/blog/detail.html мы перезаписываем или скрываем шаблон по умолчанию blog/templates/blog/detail.html .

Переиспользование Django приложений

Допустим, вы используете предлагаемую структуру проекта некоторое время, однажды, вы поймете, что ваш новый проект нуждается в блоге и один из ваших проектов прекрасно к этому подходит. Вы скопируете файлы в … НЕ ПРАВИЛЬНО! Теперь вы имеете две копии приложения. Исправления ошибок или новые функции в одном, будут вручную переноситься между проектами если предположить, что вы всегда помните про это.

Вместо этого, сделайте новый репозиторий для вашего блога и вставьте в него директорию foo/blog/ . И настройте, чтобы ваш существующий проект foo и новый проект, для установки блога через pip.

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

Дополнительные ресурсы

Наши друзья Дэнни и Аудрей из CartWheel Web напомнили нам про Cookie Cutter и специальный cookiecutter-django от Дэнни, мощная утилита для создания начального проекта, быстро и повторяемо.

Кроме того, если вы ищете все про Django уловки и рекомендации, вы не можете пройти мимо книги Two Scoops of Django: Best Practices For Django 1.6 которую мы рекомендуем всем нашим клиентам.

Обратная связь

Мы надеемся, вы нашли данное улучшение архитектуры проекта полезным. Если вы нашли какой-то баг или имеет предложение иил просто хотите пообщаться, пишите нам. Спасибо за прочтение.

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

Почему сборка пакетов так важна?

Помимо того, что это просто хороший тон, существуют еще три практические причины для поставки программного обеспечения в виде пакетов:

  • простота использования;
  • стабильность (при управлении версиями);
  • распространение.

При выборе приложения простота его установки учитывается пользователями далеко не в последнюю очередь, поэтому следует максимально упростить этот процесс. Сборка пакетов позволяет сделать программное обеспечение более доступным и простым в установке. Если установка не сложная, значит, пользователям будет проще приступить к работе с вашим программным обеспечением. Повысить доступность своего пакета при его публикации в каталоге пакетов Python (Python Package Index — PyPI) можно посредством таких утилит как pip или easy_install . (См. для получения дополнительной информации по данным средствам.)

Кроме того, управление версиями пакетов позволяет пользователям «закрепить» свои проекты, использующее ваше программное обеспечение, за его определенной версией. Например, закрепление за Pinax версии 0.9a2.dev1017 будет выглядеть таким образом:

Pinax==0.9a2.dev1017

Это принудительно свяжет проект с Pinax версии 0.9a2.dev1017.

Управление версиями обеспечивает лучшую устойчивость при внесении изменений в программное обеспечение в будущем, в результате которых могут возникнуть конфликты в интерфейсах. В итоге ваши пользователи точно знают, что они получают, и им легче отслеживать различия в разных версиях. К тому же, разработчикам проектов точно известно, над чем они работают.

Наиболее популярным методом публикации пакетов на PyPI (или на вашем собственном дистрибутивном сервере) является создание дистрибутива исходного кода для его свободной загрузки. Дистрибутив исходного кода — это стандартный способ сборки кода вашего проекта в качестве распространяемого модуля. Можно также создавать бинарные дистрибутивы, но для целей открытого использования имеет смысл также распространять свой код. Создавая дистрибутивы исходного кода, вы облегчаете пользователям процесс нахождения программного обеспечения в сети Интернет с помощью автоматизированных средств, а также его загрузки и установки. Этот процесс помогает не только в разработке на локальных системах, но и в развертывании вашего программного обеспечения.

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

Анатомия файла setup.py

Одно из предназначений сценария setup.py — это исполнение сборки пакетов вашего программного обеспечения и загрузки его на дистрибутивные серверы. На различных популярных репозиториях Python вы можете найти сценарии setup.py различного содержания. В данной статье рассмотрены основные из них. См. раздел для получения дополнительной информации.

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

python setup.py register python setup.py sdist upload

Первая команда, register , получает информацию, которую выдает функция setup() сценария setup.py, и создает запись в PyPI для вашего пакета. Она ничего не загружает, вместо этого она создает метаданные о вашем проекте с тем, чтобы впоследствии вы могли выгрузить и разместить там свои версии ПО. Следующие две команды связаны: sdist upload создает дистрибутив исходного кода, а затем выгружает его в PyPI. Тем не менее, существуют несколько необходимых условий, таких как настройка собственного конфигурационного файла.pypirc и собственно запись содержимого в файл setup.py.

Прежде всего, сконфигурируйте файл.pypirc. Он должен находиться в основном каталоге, который может быть разным в зависимости от используемой операционной системы. В операционных системах UNIX®, Linux® и Mac OS Xзайти в этот каталог можно, набрав cd ~/ . Содержимое файла должно включать ваши учетные данные PyPI, как показано в.

Листинг 1. Типовой файл.pypirc
index-servers = pypi username:xxxxxxxxxxxxx password:xxxxxxxxxxxxx

Далее переходите в PyPI и зарегистрируйтесь для создания учетной записи (не волнуйтесь — это бесплатно). Введите такое же имя пользователя и пароль, что и в файле.pypirc каталога PyPI, и убедитесь, что файл называется именно ~/.pypirc .

Теперь при написании своего сценария setup.py вам необходимо решить, что будет отображаться на индексной странице PyPI, и определиться с названием проекта. Начнем с копирования шаблона для setup.py, который я использую для проектов (см. ). Пропустив импортирование и функции, взгляните на нижнюю часть шаблона и подумайте, что вам нужно изменить с учетом особенностей вашего проекта. См. для получения ссылки на полный сценарий.

Листинг 2. Шаблон setup.py
PACKAGE = "" NAME = "" DESCRIPTION = "" AUTHOR = "" AUTHOR_EMAIL = "" URL = "" VERSION = __import__(PACKAGE).__version__ setup(name=NAME, version=VERSION, description=DESCRIPTION, long_description=read("README.rst"), author=AUTHOR, author_email=AUTHOR_EMAIL, license="BSD", url=URL, packages=find_packages(exclude=["tests.*", "tests"]), package_data=find_package_data(PACKAGE, only_in_packages=False), classifiers=[ "Development Status:: 3 - Alpha", "Environment:: Web Environment", "Intended Audience:: Developers", "License:: OSI Approved:: BSD License", "Operating System:: OS Independent", "Programming Language:: Python", "Framework:: Django", ], zip_safe=False,)

Во-первых, следует помнить, что этот шаблон подразумевает наличие в вашем проекте двух различных файлов. Первый используется для длинного описания (long_description). Он считывает содержимое файла README.rst, находящегося в той же директории, что и setup.py, и передает это содержимое как строку в параметр long_description . Этот файл заполняет целевую страницу в PyPI, поэтому желательно дать в нем краткое описание проекта и привести несколько примеров его использования. Второй файл — файл пакетов __init__.py . Мы не приводим здесь его развернутого описания, однако когда строка, которая определяет переменную VERSION, импортирует ваш пакет, Python требуется файл __init__.py, поэтому в данном модуле следует определить переменную с названием __version__ . Пока достаточно записать это строкой:

# __init__.py __version__ = "0.1"

Теперь взглянем на остальные исходные параметры.

  • PACKAGE — это пакет Python в вашем проекте. Это папка верхнего уровня, содержащая модуль __init__.py, который должен находиться в той же директории, что и файл setup.py, например: /- |- README.rst |- setup.py |- dogs |- __init__.py |- catcher.py

    Итак, в данном случае вашим пакетом будет dogs .

  • Параметр NAME обычно схож или совпадает с названием пакета PACKAGE, но вы можете задать любое имя в зависимости от ваших предпочтений. NAME — это параметр, по которому пользователи будут ссылаться на ваше программное обеспечение, имя, под которым ваше программное обеспечение будет отображаться в PyPI и, что более важно, под которым пользователи будут его устанавливать (например, pip install NAME).
  • DESCRIPTION — краткое описание вашего проекта. Одного предложения будет достаточно.
  • AUTHOR и AUTHOR_EMAIL — это соответственно: ваше имя и адрес электронной почты. Эта информация не обязательна, но указать свой адрес электронной почты для пользователей, которые пожелают обратиться к вам с вопросами по проекту, это правило хорошего тона.
  • URL — это URL-адрес проекта. Этот параметр может быть как Web-сайтом проекта или репозиторием Github, так и любым другим URL-адресом. Эта информация также не обязательна.

Возможно, вы пожелаете указать лицензионные условия и классификаторы. Более детальная информация о создании файла setup.py приведена в документации по Python. (См. .)

Управление версиями

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

Стандарт по управлению версиями пакетов Python можно найти в PEP-386 (Предложение по развитию Python) (см. .) В нем прописаны правила практического характера. Даже если вы не читали, не поняли или даже не согласны с PEP, все же разумнее придерживаться установленных в нем правил, так как именно они все чаще применяются при создании разработчиками приложений Python.

Кроме того, управление версиями необходимо не только для разработки стабильных версий, загружаемых в PyPI, но также полезно для разработки версий с суффиксом devNN . Как правило, размещение разрабатываемых версий в PyPI не поощряется, но можно сделать их общедоступными посредством настройки собственного общедоступного (или закрытого) дистрибутивного сервера. В этом случае пользователи, которые желают воспользоваться последней версией, могут указать это в своем pip -файле requirements.txt. Ниже приведено несколько примеров управления версиями:

1.0.1 # 1.0.1 final release 1.0.2a # 1.0.2 Alpha (for Alpha, after Dev releases) 1.0.2a.dev5 # 1.0.2 Alpha, Dev release #5

Публикация

Пользователям не удастся отыскать и установить ваше программное обеспечение, если оно не будет опубликовано. Обычно пакеты публикуются в PyPI. Настроив свой конфигурационный файл.pypirc и передав команду upload в setup.py, вы передадите пакет в PyPI. Как правило, эта операция производится совместно с созданием дистрибутива исходного кода:

python setup.py sdist upload

В случае использования собственного дистрибутивного сервера, добавьте раздел для авторизации в своем файле.pypirc для этого нового местоположения и укажите ссылку на него при выгрузке:

python setup.py sdist upload -r mydist

Настройка собственного дистрибутивного сервера

Главной причиной использования собственного дистрибутивного сервера для проектов с открытым исходным кодом является потребность в публикации разрабатываемых версий, так как PyPI может содержать только стабильные приложения. Например, возможно вы захотите:

pip install MyPackage

Установить последнюю стабильную версию в PyPI. Но если вы позднее добавите разрабатываемые версии, то эта команда остановит выполнение и установит последнюю версию, т. е. разрабатываемую версию. Как правило, полезно всегда закреплять проекты за определенной версией, но это делают не все пользователи. Поэтому следует убедиться в том, что, если номер версии не указан, по умолчанию возвращается последняя стабильная версия.

Одним из способов убить одним выстрелом двух зайцев (предоставлять только стабильные версии для использования pip по умолчанию и обеспечить пользователям возможность устанавливать пакеты разрабатываемых версий) является создание собственного дистрибутивного сервера. Проект Pinax применяет эту технологию для всех своих разрабатываемых версий на сайте http://dist.pinaxproject.com. (См. .)

Дистрибутивный сервер представляет собой каталог, работающий по протоколу HTTP и предоставляющий доступ к файлам на вашем сервере. Он должен иметь следующую файловую структуру:

/index-name/package-name/package-name-version.tar.gz

В дальнейшем при желании сервер можно сделать закрытым путем конфигурирования Basic-Auth на своем Web-сервере. Вы также можете добавить некоторые другие средства для выгрузки дистрибутивов исходного кода. Для этого необходимо добавить код управления выгрузкой, разобрать название файла и создать пути по каталогу, которые бы соответствовали приведенной выше схеме. Такая структура принята для проектов Pinax с использованием нескольких репозиториев.

pip и virtualenv

Хотя данная статья посвящена в основном сборке пакетов, дабы отдать должное тем преимуществам, которые сборка пакетов и управление версиями дают вашим пользователям, этот раздел описывает использование пакетов.

Инструмент pip можно установить напрямую, однако я рекомендую использовать его в рамках функциональности virtualenv . (См. .) Я также советую прибегать к virtualenv во всех случаях, когда вы имеете дело с Python, так как окружение Python при этом остается незагроможденным. Подобно тому, как виртуальная машина позволяет запускать несколько операционных систем одновременно, virtualenv позволяет запускать несколько окружений Python одновременно. Я ничего не устанавливаю в своей системе Python, а просто создаю новое виртуальное окружение для каждого нового проекта или утилиты, над которыми работаю.

Теперь, когда инструмент virtualenv установлен, можно и немного поиграть:

$ mkvirtualenv -no-site-packages testing $ pip install Pinax $ pip freeze|grep Pinax $ pip uninstall Pinax $ pip install -extra-index-url=http://dist.pinaxproject.com/fresh-start/ Pinax==0.9a2.dev1017 $ pip freeze|grep Pinax

Обратите внимание, что первая установка pip загружается и устанавливается с PyPI. Команда pip freeze выводит все версии пакетов, установленных в текущем virtualenv . Команда pip uninstall делает именно то, о чем говорит ее название: удаляет себя из virtualenv . Затем мы устанавливаем разрабатываемую версию из репозитория перезагрузки по адресу http://dist.pinaxproject.com, чтобы получить разрабатываемую версию Pinax 0.9a2.dev1017.

Переходить на Web-сайт, загружать tar-архивы и создавать коды символических ссылок (symlink) на каталог site-packages не требуется. (Раньше я так и делал, и это вызывало много проблем.) Все это ваши пользователи получают благодаря хорошей сборке пакетов, публикации и управлению версиями созданного проекта.

Заключение

Надеюсь, материала, изложенного в данной статье, достаточно для того, чтобы вы смогли приступить к работе. В разделе приведены ссылки на документацию, которая может помочь вам глубже разобраться в упомянутых вопросах. Если у вас возникнут какие-либо вопросы, заходите на Freenode и ищите меня в таких разделах чата как #pinax и #django-social (по псевдониму "paltman") или в Twitter (@paltman).