Моя цель:
Я намерен следовать методологии «Двенадцатифакторного приложения» при создании моего приложения Django на Heroku.
Вступление:
Я следую краткому руководству по началу работы с Django на Heroku. На данный момент у меня следующая структура каталогов:
~/Projects/
hellodjango_rep/
.env (empty)
.git
.gitignore
Procfile
requirements.txt
hellodjango/
manage.py
hellodjango/
__init__.py
settings/
urls.py
wsgi.py
Я установил django-toolbelt, создал свое простое приложение Django, запустил процесс в моем Procfile ... Казалось, все работает нормально, но проблемы начались, когда я настроил приложение для среды Heroku и добавил:
import dj_database_url
DATABASES['default'] = dj_database_url.config()
в конец моего файла settings.py.
Я отправил репозиторий своего приложения в Heroku, успешно $ heroku open
зашел в приложение в браузере, но локально: dj_database_url.config()
вернул пустой словарь.
Локально:
OS X 10.8.4
pip == 1.4.1
virtualenv == 1.10.1
virtualenvwrapper == 4.1.1
wsgiref == 0.1.2
Postgres.app, работающий на порту 5432
Переменные среды:
mac-pol:hellodjango_rep oubiga$ python
>>> import os
>>> os.environ
{
'PROJECT_HOME': '/Users/oubiga/Projects'...
'PATH': '/usr/local/heroku/bin:/usr/local/share/python:/usr/local/bin:/Applications/Postgres.app/Contents/MacOS/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin'...
'HOME': '/Users/oubiga'...
'WORKON_HOME': '/Users/oubiga/Envs'...
'VIRTUALENVWRAPPER_HOOK_DIR': '/Users/oubiga/Envs'...
'PWD': '/Users/oubiga/Projects/hellodjango_rep'
}
hellodjango_venv:
Django == 1.5.2
dj-database-url == 0.2.2
dj-static == 0.0.5
django-toolbelt == 0.0.1
gunicorn == 18.0
psycopg2 == 2.5.1
статический == 0.4
Вот что у меня в файле wsgi.py:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hellodjango.hellodjango.settings")
from django.core.wsgi import get_wsgi_application
from dj_static import Cling
application = Cling(get_wsgi_application())
Вот что у меня есть в моем файле manage.py:
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hellodjango.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
Вот что у меня в Procfile:
web: gunicorn hellodjango.hellodjango.wsgi
Переменные среды:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ python hellodjango/manage.py shell
>>> import os
>>> os.environ
{
'PROJECT_HOME': '/Users/oubiga/Projects'...
'PATH': '/Users/oubiga/Envs/hellodjango_venv/bin:/usr/local/heroku/bin:/usr/local/share/python:/usr/local/bin:/Applications/Postgres.app/Contents/MacOS/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin',
'HOME': '/Users/oubiga'...
'WORKON_HOME': '/Users/oubiga/Envs'...
'VIRTUAL_ENV': '/Users/oubiga/Envs/hellodjango_venv'...
'VIRTUALENVWRAPPER_HOOK_DIR': '/Users/oubiga/Envs'...
'PWD': '/Users/oubiga/Projects/hellodjango_rep'...
'DJANGO_SETTINGS_MODULE': 'hellodjango.settings'
}
На Heroku:
Переменные среды:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ heroku run python hellodjango/manage.py shell
>>> import os
>>> os.environ
{
'DATABASE_URL': 'postgres://dbuser:[email protected]:5432/dbname',
'HEROKU_POSTGRESQL_ORANGE_URL': 'postgres://dbuser:[email protected]:5432/dbname',
'LIBRARY_PATH': '/app/.heroku/vendor/lib', 'PWD': '/app'...
'DJANGO_SETTINGS_MODULE': 'hellodjango.settings',
'PYTHONHOME': '/app/.heroku/python'...
'PYTHONPATH': '/app/'...
'DYNO': 'run.9068',
'LD_LIBRARY_PATH': '/app/.heroku/vendor/lib'...
'HOME': '/app', '_': '/app/.heroku/python/bin/python',
'PATH': '/app/.heroku/python/bin:/usr/local/bin:/usr/bin:/bin'...
}
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ heroku config
=== damp-dusk-5382 Config Vars
DATABASE_URL: postgres://dbuser:[email protected]:5432/dbname
HEROKU_POSTGRESQL_ORANGE_URL: postgres://dbuser:[email protected]:5432/dbname
Исследовать:
Сохранить конфигурацию в среде: из приложения «Двенадцать факторов».
@adamwiggins написал:
Двенадцатифакторное приложение хранит конфигурацию в переменных среды ... Переменные окружения легко менять между развертываниями без изменения кода; в отличие от файлов конфигурации.
dj_database_url.config()
возвращает пустой объект: с форумов Heroku
@chrisantonick ответил:
... dj_database_url.config () получает учетные данные Postgres из переменных среды Heroku. Но на вашем локальном компьютере этих переменных нет. Вы должны поместить их в свой сценарий оболочки / venv / bin / activate ... поместите туда переменные. что-то вроде
DATABASE_URL = "xxx"
экспорт DATABASE_URL
Для каждой нужной вещи. Затем ... "деактивировать" ... и ... "активировать" снова, чтобы перезапустить его.
При запуске инструкций Django и Heroku возникла ошибка "Неправильная настройка": на форумах Heroku
@jwpe ответил:
... dj-database-url - отличная утилита, поскольку она позволяет вам использовать точно такой же код settings.py в ваших средах разработки и производства, как рекомендовано в «12-факторных принципах приложения» ... what dj_database_url.config () ищет переменную среды DATABASE_URL, а затем анализирует ее в предпочтительном формате Django ... если вы вручную не создали и не продвинули базу данных postgres на Heroku, DATABASE_URL не будет присутствовать, и возникнет ошибка ImproperlyConfigured . Установка значения по умолчанию для dj_database_url.config () в качестве URL-адреса вашей локальной БД - это один из способов убедиться, что ваше приложение будет работать в среде разработки. Однако это не обязательно единственный способ. Возможно, лучшая альтернатива - вручную установить DATABASE_URL в локальном файле .env. Затем при локальном запуске приложения с помощью Foreman оно будет загружено как переменная среды, и dj_database_url найдет ее. Таким образом, ваш .env будет содержать:
DATABASE_URL=postgres://user:pass@localhost/dbname
Это означает, что в
settings.py
вам потребуется только:
DATABASES['default']= dj_database_url.config()
... Преимущество использования локальной переменной среды вместо одной жестко запрограммированной по умолчанию состоит в том, что ваш код будет работать в любой среде, где установлен DATABASE_URL. Если вы измените имя своей локальной БД или хотите запустить код на другом компьютере разработчика, вам нужно только обновить файл .env вместо того, чтобы возиться с settings.py.
Как управлять настройками Django для производства / подготовки / разработки? с форумов Heroku
@rdegges ответил:
... пытаясь заставить ваше приложение вести себя таким образом, чтобы:
- Когда вы запускаете приложение на своем ноутбуке, оно использует ваш локальный сервер Postgres.
- Когда вы запускаете приложение в своем промежуточном приложении Heroku, оно использует надстройку сервера Postgres.
- Когда вы запускаете приложение в своем производственном приложении Heroku, оно использует надстройку сервера Postgres.
Лучший способ добиться этого - использовать переменные среды!… Переменные среды - самый элегантный (и масштабируемый) способ управления конфигурацией приложения между различными средами… Вместо того, чтобы иметь много файлов настроек, определите один файл: settings.py и он использует переменные среды для получения служебной информации и учетных данных ... На Heroku вы можете установить переменные среды вручную, запустив:
$ heroku config:set SOME_VARIABLE=some_value
... всегда есть отличный инструмент Кеннета Рейца для автообъявлений. Это позволяет вам определить простой файл .env в каталоге вашего проекта ... И каждый раз, когда вы входите в каталог проекта, эти переменные среды будут автоматически устанавливаться, так что вам не придется делать ничего особенного! Просто запустите свой проект и все заработает как положено:
python manage.py runserver
В качестве первой попытки:
Я вручную установил DATABASE_URL
в моем файле .env: DATABASE_URL=postgres://dbuser:[email protected]:5432/dbname
Но когда я запускаю команду $ foreman start
:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
17:25:39 web.1 | started with pid 319
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Starting gunicorn 18.0
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Listening at: http://0.0.0.0:5000 (319)
17:25:39 web.1 | 2013-09-11 17:25:39 [319] [INFO] Using worker: sync
17:25:39 web.1 | 2013-09-11 17:25:39 [322] [INFO] Booting worker with pid: 322
и попытался открыть свое приложение в браузере http://0.0.0.0:5000
:
17:26:59 web.1 | 2013-09-11 10:26:59 [322] [ERROR] Error handling request
17:26:59 web.1 | Traceback (most recent call last):
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 131, in handle_request
17:26:59 web.1 | respiter = self.wsgi(environ, resp.start_response)
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/dj_static.py", line 59, in __call__
17:26:59 web.1 | return self.application(environ, start_response)
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 236, in __call__
17:26:59 web.1 | self.load_middleware()
17:26:59 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 53, in load_middleware
17:26:59 web.1 | raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
17:26:59 web.1 | ImproperlyConfigured: Error importing middleware django.contrib.auth.middleware: "dlopen(/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so, 2): Library not loaded: @loader_path/../lib/libssl.1.0.0.dylib
17:26:59 web.1 | Referenced from: /Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so
17:26:59 web.1 | Reason: image not found"
Однако dj_database_url.config()
вернул:
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname',
'HOST': 'ec2-23-21-196-147.compute-1.amazonaws.com',
'USER': 'dbuser',
'PASSWORD': 'dbpassword',
'PORT': 5432
}
В качестве второй попытки:
Я вручную установил DATABASE_URL
в моем файле .env, изменив хост. Я заменил ec2-184-73-162-34.compute-1.amazonaws.com:5432 на localhost: 5000. $ deactivate
, а затем снова $ workon hellodjango_venv
.
DATABASE_URL=postgres://dbuser:dbpassword@localhost:5000/dbname
Но когда я запускаю команду $ foreman start
:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
17:38:41 web.1 | started with pid 687
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Starting gunicorn 18.0
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Listening at: http://0.0.0.0:5000 (687)
17:38:41 web.1 | 2013-09-11 17:38:41 [687] [INFO] Using worker: sync
17:38:41 web.1 | 2013-09-11 17:38:41 [690] [INFO] Booting worker with pid: 690
и попытался открыть свое приложение в браузере http://0.0.0.0:5000
:
17:38:46 web.1 | 2013-09-11 10:38:46 [690] [ERROR] Error handling request
17:38:46 web.1 | Traceback (most recent call last):
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 131, in handle_request
17:38:46 web.1 | respiter = self.wsgi(environ, resp.start_response)
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/dj_static.py", line 59, in __call__
17:38:46 web.1 | return self.application(environ, start_response)
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 236, in __call__
17:38:46 web.1 | self.load_middleware()
17:38:46 web.1 | File "/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 53, in load_middleware
17:38:46 web.1 | raise exceptions.ImproperlyConfigured('Error importing middleware %s: "%s"' % (mw_module, e))
17:38:46 web.1 | ImproperlyConfigured: Error importing middleware django.contrib.auth.middleware: "dlopen(/Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so, 2): Library not loaded: @loader_path/../lib/libssl.1.0.0.dylib
17:38:46 web.1 | Referenced from: /Users/oubiga/Envs/hellodjango_venv/lib/python2.7/site-packages/psycopg2/_psycopg.so
17:38:46 web.1 | Reason: image not found"
На этот раз dj_database_url.config()
вернул:
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dbname',
'HOST': 'localhost',
'USER': 'dbuser',
'PASSWORD': 'dbpassword',
'PORT': 5000
}
В качестве третьей попытки:
Я установил autoenv mac-pol:~ oubiga$ pip install autoenv
Из этой Поваренной книги Кеннет Райтц написал:
use_env() {
typeset venv
venv="$1"
if [[ "${VIRTUAL_ENV:t}" != "$venv" ]]; then
if workon | grep -q "$venv"; then
workon "$venv"
else
echo -n "Create virtualenv $venv now? (Yn) "
read answer
if [[ "$answer" == "Y" ]]; then
mkvirtualenv "$venv"
fi
fi
fi
}
в моем файле .bashrc.
Я запускаю $ foreman start
команду:
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman start
18:11:57 web.1 | started with pid 1104
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Starting gunicorn 18.0
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Listening at: http://0.0.0.0:5000 (1104)
18:11:57 web.1 | 2013-09-11 18:11:57 [1104] [INFO] Using worker: sync
18:11:57 web.1 | 2013-09-11 18:11:57 [1107] [INFO] Booting worker with pid: 1107
и попытался открыть свое приложение в браузере http://0.0.0.0:5000
: Сработало!
^CSIGINT received
18:12:06 system | sending SIGTERM to all processes
18:12:06 web.1 | 2013-09-11 11:12:06 [1107] [INFO] Worker exiting (pid: 1107)
SIGTERM received
18:12:06 web.1 | 2013-09-11 18:12:06 [1104] [INFO] Handling signal: int
18:12:06 web.1 | 2013-09-11 18:12:06 [1104] [INFO] Shutting down: Master
18:12:06 web.1 | exited with code 0
Но dj_database_url.config()
снова возвращает пустой словарь.
В качестве последней попытки:
Мне была интересна команда python manage.py runserver
, и я ее проверил.
(hellodjango_venv)mac-pol:hellodjango_rep oubiga$ foreman run python hellodjango/manage.py runserver
Validating models...
0 errors found
September 11, 2013 - 18:42:37
Django version 1.5.2, using settings 'hellodjango.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
и попытался открыть свое приложение в браузере http://127.0.0.1:8000/
: Не сработало!
Был поднят ImportError: No module named hellodjango.urls
.
Я заменил ROOT_URLCONF = 'hellodjango.hellodjango.urls'
в моем файле settings.py на ROOT_URLCONF = 'hellodjango.urls'
, и, наконец, это сработало.
Как и ожидалось, dj_database_url.config()
вернул пустой словарь.
So:
Теперь я немного ошеломлен. Боюсь, я неправильно понимаю здесь некую основную концепцию.
- Какой смысл использовать Gunicorn вместо сервера разработки Django?
- Почему
dj_database_url.config()
иногда возвращает полностью заполненный словарь, а иногда и пустой? - Могу ли я вручную установить переменные среды в файле .env? Нужно ли мне устанавливать такие инструменты, как autoenv, heroku-config ...?
Заранее спасибо.
dj_database_url.config(default='postgres://localhost/hocg')
Это то, что вам в итоге пришлось сделать? Создать базу данных через postgres, а затем дать ей URL-адрес localhost / name? - person Gowiem   schedule 26.09.2013import dj_database_url DATABASES['default'] = dj_database_url.config()
в settings.py достаточно. Вы можете проверить репозиторий dj-database-url и этот вопрос на форумах Heroku для получения более подробной информации. - person oubiga   schedule 29.09.2013