Создаем свое первое веб-приложение при помощи Django. Разворачиваем Django приложение в production на примере Telegram бота. Глобальная установка Django из пакета

Данная заметка это продолжение статьи про написание 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

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

Какой самый удобный способ организовать все эти каталоги на машине разработки? Как вы их называете, и как вы подключаете и развертываете это на сервере?

  • проекты (все проекты, над которыми вы работаете)
  • исходные файлы (само приложение)
  • рабочая копия репозитория (я использую git)
  • виртуальная среда (я предпочитаю разместить ее рядом с проектом)
  • статический корень (для скомпилированных статических файлов)
  • медиа-корень (для загруженных медиафайлов)
  • README
  • ЛИЦЕНЗИИ
  • документы
  • эскизы
  • (пример проекта, который использует приложение, предоставленное этим проектом)
  • (в случае использования sqlite)
  • все, что вам обычно нужно для успешной работы над проектом

Проблемы, которые я хочу решить:

4 ответов

Есть два типа Django-проектов, которые у меня есть в моем каталоге ~/projects/ , оба имеют немного другую структуру.:

  • Автономные сайты
  • Подключаемые приложения
Автономный веб-сайт

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

~/projects/project_name/ docs/ # documentation scripts/ manage.py # installed to PATH via setup.py project_name/ # project dir (the one which django-admin.py creates) apps/ # project-specific applications accounts/ # most frequent app, with custom user model __init__.py ... settings/ # settings for different environments, see below __init__.py production.py development.py ... __init__.py # contains project version urls.py wsgi.py static/ # site-specific static files templates/ # site-specific templates tests/ # site-specific tests (mostly in-browser ones) tmp/ # excluded from git setup.py requirements.txt requirements_dev.txt pytest.ini ...

Настройки

Основные настройки - производственные. Другие файлы (например, staging.py , development.py) просто импортирует все из production.py и переопределяет только необходимые переменные.

Для каждой среды существуют отдельные файлы настроек, например. производство, развитие. Я некоторые проекты, которые я тестировал (для тестировщика), (как проверка перед окончательным развертыванием) и heroku (для развертывания в heroku).

Требования

Я скорее задаю требования в setup.py напрямую. Только те, которые необходимы для среда разработки/тестирования У меня есть requirements_dev.txt .

Некоторые службы (например, heroku) требуют наличия requirements.txt в корневом каталоге.

setup.py

Полезно при развертывании проекта с помощью setuptools . Он добавляет manage.py в PATH , поэтому я могу запустить manage.py напрямую (в любом месте).

Приложения для конкретных проектов

Я использовал эти приложения в каталоге project_name/apps/ и импортировал их используя относительный импорт.

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

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

То же самое относится к языку, хотя иногда удобно создавать отдельный каталог локалей.

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

каталог Tmp

В корне проекта есть временная директория, исключенная из VCS. Он имел обыкновение хранить медиа/статические файлы и базу данных sqlite во время разработки. Все в tmp может быть удален в любое время без каких-либо проблем.

Virtualenv

Я предпочитаю virtualenvwrapper и поместить все venvs в каталог ~/.venvs но вы можете разместить его внутри tmp/ , чтобы сохранить его вместе.

Шаблон проекта

Я создал шаблон проекта для этой установки, django-start-template

Развертывание

Развертывание этого проекта выполняется следующим образом:

Source $VENV/bin/activate export DJANGO_SETTINGS_MODULE=project_name.settings.production git pull pip install -r requirements.txt # Update database, static files, locales manage.py syncdb --noinput manage.py migrate manage.py collectstatic --noinput manage.py makemessages -a manage.py compilemessages # restart wsgi touch project_name/wsgi.py

Вы можете использовать rsync вместо git , но все же вам нужно запустить пакет команд для обновления вашей среды.

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

Эскизы и черновики

Черновик шаблонов, которые я размещаю внутри глобального каталога templates/ . Я думаю, можно создать папку sketches/ в корне проекта, но еще не использовали ее.

Подключаемое приложение

Эти приложения обычно готовятся к публикации как открытые. Я привел пример ниже django-forme

~/projects/django-app/ docs/ app/ tests/ example_project/ LICENCE MANIFEST.in README.md setup.py pytest.ini tox.ini .travis.yml ...

Название каталогов понятно (надеюсь). Я помещал тестовые файлы вне каталога приложения, но это действительно неважно. Важно предоставить README и setup.py , поэтому пакет легко устанавливается через pip .

Мой ответ основан на моем собственном опыте работы и в основном в книге Два совпадающих Django , которые я настоятельно рекомендую, и где вы можете найти более подробное объяснение из всего. Я просто отвечу на некоторые вопросы, и любые улучшения или исправления будут приветствоваться. Но для достижения той же цели могут быть более правильные исполнители.

Проекты
У меня есть основная папка в моем личном каталоге, где я просматриваю все объекты, на которых я работаю.

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

Project_repository_folder/ .gitignore Makefile LICENSE.rst docs/ README.rst requirements.txt project_folder/ manage.py media/ app-1/ app-2/ ... app-n/ static/ templates/ project/ __init__.py settings/ __init__.py base.py dev.py local.py test.py production.py ulrs.py wsgi.py

Репозиторий
Git или Mercurial, по-видимому, являются самыми популярными системами управления версиями среди разработчиков Django. И самые популярные услуги хостинга для резервных копий GitHub и Bitbucket .

Виртуальная среда
Я использую virtualenv и virtualenvwrapper. После установки второго нужно настроить рабочий каталог. Mine находится в каталоге my/home/envs, так как это рекомендуется в руководстве по установке virtualenvwrapper. Но я не думаю, что самое главное, где оно размещено. Самое главное при работе с виртуальными средами - обновлять файл requirements.txt.

Pip freeze -l > requirements.txt

Статический корень
Папка проекта

Корень СМИ
Папка проекта

README
Корень репозитория

ЛИЦЕНЗИЯ
Корень репозитория

Документы
Корень репозитория. Эти пакеты python могут помочь вам упростить вашу документацию:

Эскизы

Примеры

База данных

Мне не нравится создавать новый каталог settings/ . Я просто добавляю файлы с именем settings_dev.py и settings_production.py , поэтому мне не нужно редактировать BASE_DIR . Приведенный ниже подход увеличивает структуру по умолчанию вместо изменения.

Mysite/ # Project conf/ locale/ en_US/ fr_FR/ it_IT/ mysite/ __init__.py settings.py settings_dev.py settings_production.py urls.py wsgi.py static/ admin/ css/ # Custom back end styles css/ # Project front end styles fonts/ images/ js/ sass/ staticfiles/ templates/ # Project templates includes/ footer.html header.html index.html myapp/ # Application core/ migrations/ __init__.py templates/ # Application templates myapp/ index.html static/ myapp/ js/ css/ images/ __init__.py admin.py apps.py forms.py models.py models_foo.py models_bar.py views.py templatetags/ # Application with custom context processors and template tags __init__.py context_processors.py templatetags/ __init__.py templatetag_extras.py gulpfile.js manage.py requirements.txt

Я уже очень давно слежу за развитием проекта DjangoCMS и честно скажу что он не всегда мне нравился. Но постепенно команда проекта исправила многие косяки и сделала эту CMS по-настоящему удобной, гибкой и функциональной. После этого я стал практически фанатом DjangoCMS и использую его в некоторых своих проектах (например этот блог). Сегодня я подробно расскажу что такое DjangoCMS , в каких случаях его удобно применять и покажу как с помощью него создать простой сайт. Надеюсь вы тоже полюбите этот инструмент:)

На данный момент основная проблема DjangoCMS - отсутствие нормальной документации. Первое что я нашёл на официальном сайте проекта , это инструкция как создать сайт с помощью DjangoCMS и развернуть его на облачной платформе Divio Cloud . Из этой инструкции конечно можно выцепить какое-то количество полезной информации, но я как разработчик, жду совсем другого, тем более что я не планирую использовать Divio Cloud , а хочу развернуть приложение на DjangoCMS где-нибудь у себя. Самое интересное, что существует официальная документация для разработчиков по DjangoCMS , но данную ссылку я нашёл в файле README.md из репозитория проекта на GitHub, в то время как на сайте её почему-то нет.

Есть одна вещь, за которую стоит отдельно похвалить команду Divio - грамотная поддержка в online-чате на сайте проекта DjangoCMS , куда можно задавать вопросы любой сложности! Многие вещи о которых не сказано в документации я узнал лично от ребят из Divio во время переписки с ними. Там есть и наши соотечественники которые отвечали по русски, за что им отдельный респект:)

Хватит лирики, приступаем к созданию собственного сайта на DjangoCMS !

Установка DjangoCMS

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

Virtualenv env source env/bin/activate

Если вы хотите использовать в своём проекте Python 3 , то первую команду нужно заменить на:

Virtualenv --python=/usr/bin/python3.5 env

Только не забудьте проверить правильность пути к интерпретатору Python 3 , так как у вас он может отличаться.

После того как виртуальное окружение создано и активировано нам нужно поставить установщик DjangoCMS - пакет djangocms-installer :

Pip install djangocms-installer

djangocms-installer ставит все необходимые пакеты для работы DjangoCMS . После этого ваше виртуальное окружение начинает поддерживать команду djangocms , которой мы скоро воспользуемся.

Создаём директорию для нашего проекта и переходим в неё:

Mkdir django_cms_project cd django_cms_project

И наконец создаём наше приложение на DjangoCMS с помощью команды:

Djangocms -f -p . django_cms_example

  • Флаг -f говорит о том что дополнительно будет установлен инструмент Django Filer , который отвечает за работу с файловой системой. Мне данный инструмент нравится и я рекомендую его использовать.
  • Флаг -p с точкой (-p . ) задаёт текущую директорию как родительскую для проекта.
  • djangocms_blog - название нашего приложения. Вы можете указать своё собственное.

В старых версиях установщик DjangoCMS задавал вопросы по конфигурированию приложения во время установки. В новой версии приложение конфигурируется автоматически, а так же создаётся суперпользователь с логином admin и паролем admin . После установки вы можете запустить приложение командой:

Python manage.py runserver

После выполнения команды откройте в браузере ссылку http://127.0.0.1:8000/ . Если всё сделано правильно, вы должны увидеть форму входа в панель администрирования Django :

Для входа просто введите логин admin и пароль admin . На этом процесс установки DjangoCMS можно считать завершённым.

Настройка

Откройте в своей любимой IDE (лично я предпочитаю PyCharm ) только что созданный проект. В моём случае файлы проекта располагаются в директории djangocms_blog_project . Структура созданного проекта должна быть примерно такой:

Как Вы видите, это обычный Django -проект, только с прикрученным DjangoCMS в настройках (файл settings.py ). В целом наш проект и так прекрасно запускается и работает, но Вы должны помнить что по умолчанию будет использоваться база данных SQLite , которая хорошо подходит для отладки, но совсем не подходит для работы в реальных условиях. Кроме этого DjangoCMS очень много информации хранит именно в базе: контент, меню, список страниц, настройки каждой страницы, посты и т.д. То есть при переходе на другую базу данных придётся делать миграцию и я рекомендую сразу использовать ту базу данных, дамп которой можно потом перенести на продакшен. Но это просто рекомендация, можно успешно отладить приложение, используя SQLite и фейковую информацию на страницах, а затем на новой базе собрать чистовой вариант уже на отлаженных шаблонах. Или же, как правильно заметил Dmytro Kyrychuk в комментариях, использовать команды manage.py dumpdata и loaddata (эти команды подробно описаны тут: https://docs.djangoproject.com/en/1.10/ref/django-admin/ ​) для того, чтобы сдампить одну базу в JSON и восстановить дамп уже на другой базе.

Так как мой проект демонстрационный, я оставляю настройки базы данных без изменений:

DATABASES = { "default": { "CONN_MAX_AGE": 0, "ENGINE": "django.db.backends.sqlite3", "HOST": "localhost", "NAME": "project.db", "PASSWORD": "", "PORT": "", "USER": "" } }

Других настроек на данном этапе не требуется.

Создание шаблонов

Прежде чем создавать страницы нашего сайта-блога нам нужны шаблоны на основе которых будут создаваться эти самые страницы. Наверняка вы захотите использовать собственный неповторимый дизайн чтоб было лучше чем у соседа, поэтому нам нужно в начале погрузиться в вёрстку. Шаблоны DjangoCMS это обычные файлы в формате .html с некоторым количеством шаблонных тегов Django и DjangoCMS . При создании нового проектаавтоматически генерируется 4 шаблона в папке templates (в моём случае djangocms_blog_project/djangocms_blog/templates) :

  • base.html - базовый шаблон, от которого наследуются все остальные шаблоны
  • fullwidth.html - шаблон полноразмерной страницы с контентом на всю ширину экрана
  • sidebar_left.html - страница с левым сайдбаром
  • sidebar_right.html - страница с правым сайдбаром

Кроме того, список шаблонов обязательно должен быть задан в settings.py в переменной CMS_TEMPLATES для того чтобы можно было выбрать нужный шаблон в интерфейсе при создании новой страницы сайта. По умолчанию у нас сконфигурировано 3 шаблона (все кроме base.html ):

CMS_TEMPLATES = (## Customize this ("fullwidth.html", "Fullwidth"), ("sidebar_left.html", "Sidebar Left"), ("sidebar_right.html", "Sidebar Right"))

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

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

Выберите пункт Новая страница (Создать страницу рядом с текущей) и нажмите Далее . Откроется вот такое окно:

Заполните заголовок (Главная ), путь к странице (index ) и содержимое (Hello world! ), а затем нажмите кнопку Создать . Всё! Страница готова:

Теперь в верхнем меню выберите Страница > Шаблоны :

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

Теперь предлагаю подробно разобрать код шаблона fullwidth.html , но так как он наследуется от base.html , то начнём с базового шаблона:

{% block title %}This is my new project home page{% endblock title %} .nav { padding-left: 0; } .nav li { display: inline; list-style-type: none; padding-right: 20px; } .container { width: 940px; margin: 0 auto } .content { float: left; width: 80%; } .sidebar { float: left; width: 20%; } {% render_block "css" %} {% cms_toolbar %} {% render_block "js" %}

Что тут происходит? Да ничего особенного. В первой строке мы загружаем шаблонные теги:

  • cms_tags - теги DjangoCMS (http://docs.django-cms.org/en/release-3.4.x/reference/templatetags.html)
  • menu_tags - теги для управления меню (http://docs.django-cms.org/en/release-3.4.x/reference/navigation.html)
  • sekizai_tags - теги django-sekizai (https://django-sekizai.readthedocs.io/en/latest/)

Так же у нас в шаблоне 2 блока, которые можно переопределить в дочерних шаблонах: {% block title %} и {% block content %} .

Кроме этого у нас есть:

  • тег ответственный за отображение тулбара DjangoCMS - {% cms_toolbar %}
  • теги django-sekizai , которые отвечают за размещение блоков со ссылками на css и js в определённых частях страницы - {% render_block "css" %} и {% render_block "js" %}
  • тег, ответственный за отображение меню - {% show_menu 0 100 100 100 %}

Всё остальное вы и так знаете. Переходим к шаблону fullwidth.html :

{% extends "base.html" %} {% load cms_tags %} {% block title %}{% page_attribute "page_title" %}{% endblock title %} {% block content %} {% placeholder "content" %} {% endblock content %}

По факту перед нами стандартный шаблон Django отнаследованный от base.html . Из интересного тут 2 тега DjangoCMS :

  • тег {% page_attribute "page_title" %} - отображает атрибут страницы page_title в блоке title . Данный атрибут задаётся при создании страницы и является её заголовком. Все атрибуты можно просмотреть в документации .
  • тег {% placeholder "content" %} - это очень важный тег, который задаёт изменяемую часть страницы в блоке content . Количество плейсхолдеров на странице может быть неограниченным, главное чтоб название каждого плейсхолдера было уникальным. В панели администратора DjangoCMS можно менять содержимое любого плейсхолдера на своё усмотрение, например туда можно добавить текст, ссылку, картинку и т.д., а можно всё сразу и в любых комбинациях:)

Вот вы уже имеете некоторое представление о шаблонах DjangoCMS . Приведённые выше шаблоны я полностью изменю и доработаю, так как хочу чтобы сайт имел красивый дизайн. Это всё реализуется очень просто, но прежде чем менять шаблоны, давайте заглянем в панель администрирования DjangoCMS , для того чтобы лучше разобраться с плейсхолдерами. Нажмите кнопку Структура на верхней панели и вы увидите вот такую страницу:

Содержимое - это наш плейсхолдер content из шаблона fullwidth.html . Он содержит один единственный плагин, который отображает строчку Hello world! . Вы можете в любой момент отредактировать содержимое плагина, а так же добавлять другие плагины в плейсхолдер и даже создавать свои собственные плагины (об этом я расскажу в другой статье).

Для наглядности добавим ещё один плагин в плейсхолдер content . Для этого нажмите кнопку + и в появившемся окне выберите из списка плагин Google Map :

В открывшемся окне задайте название карты (поле MAP TITLE ), а так же широту и долготу своего города (поля LATITUDE и LONGITUDE ). В качестве названия у меня просто слово Карта , широта 55.751244 , долгота 37.618423 :

В верхней панели появилась синяя кнопка Опубликовать изменения страницы . Нажмите её и вы увидите обновлённую главную страницу с картой:

Вот так легко и просто можно управлять содержимым страницы в DjangoCMS .

Теперь я покажу как кардинально изменить дизайн сайта. Больше всего мне нравится в DjangoCMS то что можно взять практически любой html -шаблон и с минимальными изменениями встроить его в свой проект. В качестве примера я нашёл в интернете бесплатный адаптивный шаблон, свёрстанный с помощью CSS -фреймворка Bootstrap .

Для начала изменим содержимое базового шаблона base.html :

{% load cms_tags menu_tags sekizai_tags %} {% render_block "css" %} {% cms_toolbar %} Меню Меню Алексей Кутепов

{% block header %} {% placeholder "title" %} {% placeholder "sub_title" %} {% endblock header %} {% block content %}{% endblock content %} {% render_block "js" %}

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

Как всегда в самом начале мы должны загрузить все необходимые шаблонные теги:

{% load cms_tags menu_tags sekizai_tags %}

{% block title %}Сайт Алексея Кутепова{% endblock title %}

{% render_block "css" %}

Обратите внимание на переменную {{ STATIC_URL }} - в место него Django автоматически подставляет путь до папки со статикой. Так же в конце присутствует тег {% render_block "css" %} , который на данном этапе бесполезен, но при усложнении шаблона может здорово помочь: вместо этого тега можно динамически подставлять таблицы стилей в зависимости от определённых условий.

После тега нужно не забыть поставить шаблонный тег {% cms_toolbar %} , так как он отвечает за отображение верхней панели инструментов в режиме редактирования сайта. Как вы могли убедиться, мы её используем довольно часто и без неё у нас просто не будет возможности вносить изменения.

Меню Меню Алексей Кутепов

В шаблоне предусмотрен красивый хедер с фоновым изображением. Код, который отвечает за отображение хедера я заключил в блок header для того чтобы его можно было переопределить в дочерних шаблонах. Кроме того, в хедере у нас есть заголовок и подзаголовок, вместо которых я добавил плейсхолдеры title и sub_title , для того чтобы их можно было динамически изменять. При загрузке фонового изображения обязательно используется переменная {{ STATIC_URL }} :

{% block header %} {% placeholder "title" %} {% placeholder "sub_title" %} {% endblock header %}

После хедера идёт блок content , с которым вы знакомы по предыдущему шаблону:

{% block content %}{% endblock content %}

Далее идёт футер, в котором я использовал новый шаблонный тег - . Основное отличие тега static_placeholder от placeholder заключается в том что содержимое static_placeholder наследуется дочерними шаблонами. В данном случае нам достаточно один раз задать значение {% static_placeholder "copyright" %} на главной странице и оно автоматически будет отображаться на других страницах нашего сайта:

В самом конце мы загружаем все необходимые скрипты из папки со статикой:

{% render_block "js" %}

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

Перезагрузите сервер и обновите страницу в браузере. Если вы всё сделали правильно, то должны увидеть сайт уже в обновлённом дизайне:

Пока ещё не вся информация отображается на странице, так как мы ещё не заполнили новые плейсхолдеры. Нажмите синюю кнопку Редактировать страницу на верхней панели, а затем на кнопку Структура . Как вы видите, в структуре страницы появились 3 новых плейсхолдера: Title (у меня система перевела название этого плейсхолдера на русский язык как Заголовок ), Sub_Title и Copyright .

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

Кроме того у нас ещё есть плейсхолдер content (Содержимое ), который мы заполняли ранее. Удалите из него плагин Google Map и откройте на редактирование плагин Текст . Затем нажмите кнопку Источник в редакторе и введите произвольный текст, заключённый в теги:

Произвольный текст

Я заполнил плейсхолдеры вот так:

Отлично! Теперь нас есть полноценная первая страница сайта. Давайте для примера создадим новый шаблон и сделаем ещё одну страницу. Предположим нам нужен особенный шаблон для раздела с контактами на сайте. Для этой цели создайте в папке templates файл contacts.html с таким содержимым:

{% extends "base.html" %} {% load cms_tags %} {% block title %}{% page_attribute "page_title" %}{% endblock title %} {% block header %} {% placeholder "title" %} {% placeholder "sub_title" %} {% endblock header %} {% block content %} Контакты
{% placeholder "email" %} {% placeholder "skype" %}
{% placeholder "phone" %}
Я в социальных сетях
{% placeholder "vk" %}
{% placeholder "facebook" %}
{% placeholder "linkedin" %}
{% placeholder "github" %}
{% endblock content %}

В этом коде нет ничего нового, я просто сверстал список контактов и добавил для каждого контакта свой плейсхолдер. Ещё я для красоты переопределил блок header . Теперь нужно добавить этот шаблон в settings.py :

CMS_TEMPLATES = (## Customize this ("fullwidth.html", "Fullwidth"), ("sidebar_left.html", "Sidebar Left"), ("sidebar_right.html", "Sidebar Right"), ("contacts.html", "Contacts"))

Теперь перезагрузите сервер и создайте новую страницу, выбрав в верхней панели Страница > Создать страницу > Новая страница :

Заполните все поля в появившемся окне и нажмите кнопку Сохранить и продолжить редактирование :

В новом окне нажмите кнопку Расширенные настройки и выберите шаблон Contacts из выпадающего списка:

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

Основные поля:

  • DISPLAY NAME - отображаемое название ссылки
  • EXTERNAL LINK - используется в том случае, если ссылка идёт на внешний ресурс
  • INTERNAL LINK - позволяет ссылаться на внутренние страницы сайта
  • Link settings - в этом разделе для нас интерес представляют поля, которые позволяют сформировать ссылку для электронной почты и телефона

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

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

У нас получился небольшой и красивый сайт, но так как данный проект демонстрационный, тут можно ещё много чего доработать. Теперь вы знаете основы работы с DjangoCMS и уже можете создать свой собственный сайт на основе данного фреймворка.

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

Описание процесса быстрой установки Django из Панели управления Plesk.

Статья устаревшая, относится к панели Plesk, которая больше не будет поддерживаться.

"Профи" (с подключенным SSH-доступом), "Плюс", "VIP", а так же во время тестового доступа по этим тарифам, и предлагает быстро создать новый проект Django. Для того чтобы это сделать необходимо:

  • Войти в Панель управления (учетные данные для доступа вы получаете сразу после .)
  • В главном меню панели управления выбрать пункт "Домены".
  • Выбрать домен, на который планируется установить Django.
  • В группе "Приложения и услуги" выбрать пункт "Веб-приложения".
  • В строке поиска ввести django, после чего начать установку.
  • Внимательно прочитать лицензионное соглашение, после согласия возможна дальнейшая установка.
  • В разделе "параметры установки" выбрать целевой каталог для установки приложения.
  • В разделе "Настройки базы данных" необходимо выбрать тип (На данный момент поддерживается MySQL и PostgreSQL), указать имя пользователя и пароль базы данных - данные параметры будут автоматически внесены в файл settings.py.
  • Далее необходимо ввести логин, адрес электронной почты и пароль администратора, данный пароль будет использован далее.
  • В разделе "Личные настройки" при установке пакета предоставляется доступ к настройкам Django для нового проекта, в частности:
    • "Имя Django проекта" - имя проекта Django, который будет создан.
    • "Имя директории с проектами Django" - имя директории где будут располагатьcя проекты django, данная директория будет располагатьcя в папке private на вашей площадке.
    • "Активировать интерфейс администратора" - при выборе данной опции django разворачивается с включенным админ-разделом, производится синхронизация базы данных, логин и пароль администратора устанавливается в значения, указанные выше.
    • "Свой virtualenv " - данная опция подразумевает создание собственной "инстанции" python, при этом вы получаете возможность устанавливать свои модули, которые могут отличаться от установленных на хостинг, при включении, дисковое пространство, занимаемое приложением, несколько увеличивается.
  • После установки данного приложения, по адресу http://имя_домена/директория_установки/ будет доступна стандартная страница установленной Django последней стабильной версии с Python 2.6.2, для дальнейших операций и выполнения стандартных действий, например, управление проектом через manage.py, необходим полный ssh доступ. Данная услуга доступна по-умолчанию для тарифных планов "Плюс" и "VIP", на тарифе "Профи" существует возможность получить полный ssh доступ, расширив тариф дополнительной опцией через систему биллинга . Если данный пакет по каким-либо причинам не удовлетворяет требованиям Вашего проекта, Вы можете создать 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:


    
    Top