Развертывание приложения Django на Heroku: Могу ли я вручную установить переменные среды в файле .env? Нужно ли устанавливать такие инструменты, как autoenv, heroku-config...?

Моя цель:

Я намерен следовать методологии "Двенадцать факторов" для создания моего приложения Django на Heroku.

Введение:

Я следую краткому руководству "Начало работы с Django on 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
пип == 1.4.1
virtualenv == 1.10.1
virtualenvwrapper == 4.1.1
wsgiref == 0.1.2
Postgres.app работает на Port 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:

Джанго == 1.5.2
DJ-базы данных URL == 0.2.2
DJ-статические == 0.0.5
Джанго-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:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname', 
  'HEROKU_POSTGRESQL_ORANGE_URL': 'postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com: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:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname
HEROKU_POSTGRESQL_ORANGE_URL: postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com:5432/dbname

Исследования:

Сохранить конфигурацию в среде: из приложения Twelve-Factor

@adamwiggins писал (а):

Двенадцатифакторное приложение хранит конфигурацию в переменных среды... Env vars легко изменить между развертываниями без изменения кода; в отличие от файлов конфигурации.

dj_database_url.config() возвращает пустой объект: из форумов Heroku

@chrisantonick ответил:

... dj_database_url.config() получает учетные данные Postgres из Переменные окружения Heroku. Но на вашей локальной машине эти переменных нет. Вы должны поместить их в свой /venv/bin/ активировать оболочку script... поместить туда переменные. что-то вроде
DATABASE_URL = "xxx"
export DATABASE_URL
Для каждой вещи ему нужно. Затем... "деактивировать"... и... "активировать" снова перезапустить его.

Приступая к работе с инструкциями Django и Heroku, поднял сообщение об ошибке ImproperlyConfigured: от форумов Heroku

@jwpe ответил:

... dj-database-url - отличная утилита, так как позволяет использовать точно такой же settings.py код в вашей разработке и производстве средах, как рекомендовано в "Принципах принципов 12 факторов"... что dj_database_url.config() делает поиск DATABASE_URL переменная среды, а затем разбор ее в Django формат... если вы не создали вручную и не продвинули DB на Heroku, DATABASE_URL не будет присутствовать, а Неправильно сконфигурирована ошибка. Установка значения по умолчанию для 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.

Как управлять настройками создания/размещения/dev Django? от форумов Heroku

@rdegges ответил:

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

  • Когда вы используете приложение на своем ноутбуке, он использует ваш локальный сервер Postgres.
  • Когда вы запускаете приложение в своем промежуточном приложении Heroku, он использует аддон сервера Postgres.
  • Когда вы запускаете приложение в своем приложении Heroku для производства, он использует аддон Postgres server.

Лучший способ добиться этого - использовать переменные окружения!... Переменные среды являются наиболее элегантным (и масштабируемым) способом управлять конфигурацией приложений между различными средами... Вместо того, чтобы иметь множество файлов настроек, определите один файл: settings.py и использовать переменные окружения для вытягивания сервисную информацию и учетные данные... На Heroku вы можете установить переменные среды вручную:

$ heroku config:set SOME_VARIABLE=some_value

... всегда есть отличный инструмент Кеннет Рейц. Это позволяет вам определите простой .env файл в каталоге проекта... И каждый раз, когда вы введите ваш каталог проекта, эти переменные окружения будут автоматически устанавливается так, что вам не нужно ничего особенного делать! Просто запустите проект, и все будет работать так, как ожидалось: python manage.py runserver

В качестве первой попытки:

Я вручную установил DATABASE_URL в мой .ENV файл: DATABASE_URL=postgres://dbuser:dbpassword@ec2-184-73-162-34.compute-1.amazonaws.com: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
Из этого Cookbook Кеннет Рейц написал:" Я /

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() возвращает пустой словарь.

Итак:

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

  • Какой смысл использовать gunicorn вместо сервера разработки Django?
  • Почему dj_database_url.config() иногда возвращает полностью заполненный словарь, а иногда и пустой?
  • Могу ли я вручную установить переменные среды в файле .env? Мне нужно установить такие инструменты, как autoenv, heroku-config...?

Спасибо заранее.

9
задан oubiga 12 сент. '13 в 3:03
источник поделиться

1 ответ

Я тоже застрял в postgres, вот что я сделал в settings.py, чтобы добавить локальные настройки:

DATABASES = {
'default': dj_database_url.config(default='postgres://<user>:<password>@<host>/<dbname>')
}

Конечно, вы должны создать базу данных после шагов postgres. Решение было от https://discussion.heroku.com/t/dj-database-url-config-is-returning-an-empty-object/55/9

1
ответ дан Song Keang 20 нояб. '13 в 20:47
источник поделиться

Другие вопросы по меткам