【问题标题】:Can't collectstatic to s3 via Heroku using boto - s3 bucket returns a NoneType无法使用 boto 通过 Heroku 将静态收集到 s3 - s3 存储桶返回 NoneType
【发布时间】:2012-12-23 02:19:36
【问题描述】:

这个问题与使用 Heroku、django-storages(对于 s3 带有 boto)和 CloudFront 来提供静态内容的设置有关。

过去几个小时我一直在尝试将我的静态文件成功加载到我的 Heroku 应用程序中。我已成功将 Cloudfront 连接到我的 s3 存储桶,似乎存储桶设置正确,但无论出于何种原因,我的 AWS_STORAGE_BUCKET_NAME 值似乎没有正确注册。

如果有人对如何调试有任何线索或想法,我将不胜感激。我不知道该怎么做。感谢阅读。

settings.py(重要的东西):

try:
  from settings_local import *
except:
  import s3utils
DEBUG = False
#s3 stuff
DEFAULT_FILE_STORAGE = 's3utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 's3utils.StaticRootS3BotoStorage'  
STATIC_URL = 'https://[domain].cloudfront.net/'
#use heroku postgres database
import dj_database_url
DATABASES['default'] =  dj_database_url.config()

s3utils.py

from storages.backends.s3boto import S3BotoStorage
from django.utils.functional import SimpleLazyObject
import os

AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']
AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']
AWS_STORAGE_BUCKET_NAME = 'static.[website].org'

StaticRootS3BotoStorage = lambda: S3BotoStorage(location='static')
MediaRootS3BotoStorage  = lambda: S3BotoStorage(location='media')

这是我在尝试收集静态时得到的回溯,无论是通过“heroku run”还是在 Procfile 中:

  Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 443, in execute_from_command_line
    utility.execute()
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/__init__.py", line 382, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
    output = self.handle(*args, **options)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/core/management/base.py", line 371, in handle
    return self.handle_noargs(**options)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 163, in handle_noargs
    collected = self.collect()
  File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 113, in collect
    handler(path, prefixed_path, storage)
  File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 287, in copy_file
    if not self.delete_file(path, prefixed_path, source_storage):
  File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 215, in delete_file
    if self.storage.exists(prefixed_path):
  File "/app/.heroku/python/lib/python2.7/site-packages/storages/backends/s3boto.py", line 284, in exists
    return k.exists()
  File "/app/.heroku/python/lib/python2.7/site-packages/boto/s3/key.py", line 399, in exists
    return bool(self.bucket.lookup(self.name))
  File "/app/.heroku/python/lib/python2.7/site-packages/boto/s3/bucket.py", line 148, in lookup
    return self.get_key(key_name, headers=headers)
  File "/app/.heroku/python/lib/python2.7/site-packages/boto/s3/bucket.py", line 181, in get_key
    query_args=query_args)
  File "/app/.heroku/python/lib/python2.7/site-packages/boto/s3/connection.py", line 458, in make_request
    auth_path = self.calling_format.build_auth_path(bucket, key)
  File "/app/.heroku/python/lib/python2.7/site-packages/boto/s3/connection.py", line 92, in build_auth_path
    path = '/' + bucket
TypeError: cannot concatenate 'str' and 'NoneType' objects

请注意,我省略了域名等,我实际上在代码中没有 [domain] 或 [website]。

【问题讨论】:

  • 我不想说我正在回答这个问题,因为对于为什么会出现这个问题,这确实不是一个令人满意的答案,但是在我之前的 settings.py 中放置:AWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID'] AWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY'] AWS_STORAGE_BUCKET_NAME = 'static.[website].org' try/except 块似乎有效。任何对 Python 有更好理解的人都可以解释为什么会这样吗?

标签: django heroku amazon-s3 amazon-cloudfront boto


【解决方案1】:

你不是在说from s3utils import *,所以AWS_STORAGE_BUCKET_NAME永远不会被导入到设置模块中。

S3BotoStorage 将从环境变量中拉取AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY,但AWS_STORAGE_BUCKET_NAME 必须在settings.py 中设置。这似乎是一个奇怪的不一致,但我认为这是因为AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY 实际上是boto 参数而AWS_STORAGE_BUCKET_NAME 不是(boto 将从环境变量中提取凭据)。*

对 s3utils 的其他引用是明确的:

DEFAULT_FILE_STORAGE = 's3utils.MediaRootS3BotoStorage'
STATICFILES_STORAGE = 's3utils.StaticRootS3BotoStorage'

所以,唯一没有处理的设置是AWS_STORAGE_BUCKET_NAME,这会导致您的错误。

*我希望 django-storages 接受来自 env vars (12-Factor App, anyone?) 的其他设置,并且正在考虑打开一个问题/提交一个拉取请求。

【讨论】:

  • 对不起,我从来没有接受过这个,但这正是问题所在。非常感谢!
  • 感谢您的帮助,我已完成所有设置,但“AWS_STORAGE_BUCKET_NAME”的变量名称错误,非常感谢。
猜你喜欢
  • 2014-09-04
  • 2014-04-22
  • 1970-01-01
  • 2017-09-01
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 2015-08-23
  • 2015-02-23
相关资源
最近更新 更多