在 Heroku 上部署 Django 应用程序:我可以在 .env 文件中手动设置环境变量吗?我需要安装 autoenv、heroku-config 等工具吗?
Posted
技术标签:
【中文标题】在 Heroku 上部署 Django 应用程序:我可以在 .env 文件中手动设置环境变量吗?我需要安装 autoenv、heroku-config 等工具吗?【英文标题】:Deploying Django app on Heroku: Can I manually set environment variables in the .env file? Do I need to install tools like autoenv, heroku-config...? 【发布时间】:2013-09-16 04:34:45 【问题描述】:我的目标:
我打算按照“十二要素应用程序”的方法在 Heroku 上构建我的 Django 应用程序。
简介:
我正在关注“Heroku 上的 Django 入门”快速入门指南。目前我有以下目录结构:
~/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 虚拟环境==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-静态==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: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
研究:
在环境中存储配置:来自 The Twelve-Factor App
@adamwiggins 写道:
十二因素应用程序将配置存储在环境变量中... Env vars 很容易在部署之间更改,而无需更改任何代码; 不像配置文件。
dj_database_url.config()
正在返回一个空对象:来自 Heroku 论坛
@chrisantonick 回复:
... dj_database_url.config() 从 Heroku 环境变量。 但是,在您的本地计算机上,那些 变量不存在。你必须把它们放在你的 /venv/bin/activate shell script...把变量放在那里。 类似于 DATABASE_URL = "xxx" 导出 DATABASE_URL 对于它需要的每一件事。然后......“停用”......和......“激活” 再次重新启动它。
Django 和 Heroku 入门指令引发了来自 Heroku 论坛的 ImproperlyConfigured 错误:
@jwpe 回复:
... dj-database-url 是一个很棒的实用程序,因为它允许您使用 开发和生产中完全相同的 settings.py 代码 环境,如“12 因素应用程序原则”中所推荐的……什么 dj_database_url.config() 正在寻找 DATABASE_URL 环境变量,然后解析成Django的preferred 格式...如果您还没有手动创建和提升 postgres 数据库 在 Heroku 上,DATABASE_URL 将不存在,并且 将引发 ImproperlyConfigured 错误。设置默认值 dj_database_url.config() 作为您的本地数据库 URL 是确保 您的应用程序将在开发环境中工作。 但是,它不一定是唯一的方法。也许更好 替代方法是在本地 .env 文件中手动设置 DATABASE_URL。 然后,当使用 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
...总是有 Kenneth Reitz 出色的 autoenv 工具。这让你 在你的项目目录中定义一个简单的 .env 文件……而且每次你 进入你的项目目录,那些环境变量将是 自动设置,因此您不必做任何特别的事情!只是 运行您的项目,一切都会按预期进行:
python manage.py runserver
作为第一次尝试:
我在我的 .env 文件中手动设置了DATABASE_URL
: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
作为第二次尝试:
我在更改主机的 .env 文件中手动设置 DATABASE_URL
。我用“localhost:5000”替换了“ec2-184-73-162-34.compute-1.amazonaws.com:5432”。 $ 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
从CookbookKenneth Reitz 写道,我说:
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()
再次返回一个空字典。
作为最后的尝试:
我对@987654366@ 命令很好奇,并查看了它。
(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
。
我将 settings.py 文件中的 ROOT_URLCONF = 'hellodjango.hellodjango.urls'
替换为 ROOT_URLCONF = 'hellodjango.urls'
,它终于奏效了。
正如预期的那样,dj_database_url.config()
返回了一个空字典。
所以:
现在,我感到有些不知所措。恐怕我在这里误解了一些核心概念。
使用 gunicorn 代替 Django 开发服务器有什么意义? 为什么dj_database_url.config()
有时会返回填满的字典,有时返回空字典?
能否在 .env 文件中手动设置环境变量?是否需要安装 autoenv、heroku-config...等工具?
提前谢谢你。
【问题讨论】:
作为在我的第一个 Django 应用程序中处理这些类型问题的其他人,我感受到了你的痛苦。我没有给你答案,但祝你好运。 @Gowie47 谢谢。在 IRC 上有人说 Postgres.app 与它有关。 Heroku Forums. 嗯.. 我也在本地使用 Postgres.app。我刚刚意识到我的 .config() 方法有以下内容:dj_database_url.config(default='postgres://localhost/hocg')
这就是你最终不得不做的吗?通过 postgres 创建数据库,然后给它一个 localhost/name url?
import dj_database_url DATABASES['default'] = dj_database_url.config()
在 settings.py 中就足够了。您可以查看dj-database-url repository 和this question on Heroku forums 了解更多详情。
【参考方案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
【讨论】:
以上是关于在 Heroku 上部署 Django 应用程序:我可以在 .env 文件中手动设置环境变量吗?我需要安装 autoenv、heroku-config 等工具吗?的主要内容,如果未能解决你的问题,请参考以下文章
Django:使用 sqlite3 作为数据库在 Heroku 上部署应用程序