【问题标题】:Django using Amazon S3使用 Amazon S3 的 Django
【发布时间】:2022-01-17 14:07:06
【问题描述】:

因此,每当我运行以下命令时,都会创建一个 staticfiles 文件夹,并且我无法将静态文件收集到我的 AWS S3 存储桶中。

(portfolio) PS C:\Users\arund\Desktop\Code\Django\portfolio-project> python manage.py collectstatic
Found another file with the destination path 'user\main.css'. It will be ignored since only the first encountered file is collected. If this is not what you want, make sure every static file has a unique path.

settings.py

"""
Django settings for portfolio project.

Generated by 'django-admin startproject' using Django 3.2.9.

For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
import os

SECRET_KEY = os.getenv("SECRET_KEY", default="dev key")
# SECURITY WARNING: don't run with debug turned on in production!
#DEBUG = True

DEBUG = os.environ.get('DJANGO_DEBUG', '') 

ALLOWED_HOSTS = ["url.com"]


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pages.apps.PagesConfig',
    'storages',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django_session_timeout.middleware.SessionTimeoutMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'portfolio.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'portfolio.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES['default'].update(db_from_env)

# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
# All of this is in my console.aws.amazon to configure aws s3 static files only
# IAM Management Console
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID', '') 
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY', '') 
# Amazon S3 Buckets
AWS_STORAGE_BUCKET_NAME =  os.environ.get('AWS_STORAGE_BUCKET_NAME', '') 
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'pages/static'),
]
STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
# STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'


# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

LOGIN_REDIRECT_URL = 'home'
LOGOUT_REDIRECT_URL = 'home'

SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
SESSION_ENGINE = (
'django.contrib.sessions.backends.cache'
)
SESSION_COOKIE_AGE = 10  # change expired session
SESSION_IDLE_TIMEOUT = 10  # logout

SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_SAVE_EVERY_REQUEST = True
SESSION_TIMEOUT_REDIRECT = '/accounts/login/' 

import django_heroku
django_heroku.settings(locals())

它会像这样创建另一个文件夹

试过 django_heroku.settings(locals(), staticfiles=False)

(portfolio) PS C:\Users\arund\Desktop\Code\Django\portfolio-project> git push heroku master
Counting objects: 4, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 400 bytes | 200.00 KiB/s, done.
Total 4 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/python
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote:  !     Python has released a security update! Please consider upgrading to python-3.9.9
remote:        Learn More: https://devcenter.heroku.com/articles/python-runtimes
remote: -----> Using cached install of python-3.9.6
remote: -----> Installing pip 21.3.1, setuptools 57.5.0 and wheel 0.37.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: -----> $ python manage.py collectstatic --noinput
remote:        Found another file with the destination path 'user/main.css'. It will be ignored since only the first encountered file is collected. If this is not what you want, make sure every static file has a unique path.
remote:        129 static files copied.
remote:
remote: -----> Discovering process types
remote:        Procfile declares types -> release, web
remote:
remote: -----> Compressing...
remote:        Done: 68.7M
remote: -----> Launching...
remote:  !     Release command declared: this new release will not be available until the command succeeds.
remote:        Released v169
remote:        https://url.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
remote: Running release command...
remote:
remote: Operations to perform:
remote:   Apply all migrations: admin, auth, contenttypes, sessions
remote: Running migrations:
remote:   No migrations to apply.
To ------
   74524a2..f5e5fe8  master -> master
(portfolio) PS C:\Users\arund\Desktop\Code\Django\portfolio-project> python manage.py collectstatic

You have requested to collect static files at the destination
location as specified in your settings.

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes
Traceback (most recent call last):
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\manage.py", line 22, in <module>
    main()
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\core\management\__init__.py", line 419, in execute_from_command_line
    utility.execute()
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\core\management\__init__.py", line 413, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\core\management\base.py", line 354, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\core\management\base.py", line 398, in execute
    output = self.handle(*args, **options)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 187, in handle
    collected = self.collect()
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 114, in collect
    handler(path, prefixed_path, storage)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 338, in copy_file
    if not self.delete_file(path, prefixed_path, source_storage):
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 248, in delete_file
    if self.storage.exists(prefixed_path):
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\storages\backends\s3boto3.py", line 469, in exists
    self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\client.py", line 391, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\client.py", line 691, in _make_api_call
    request_dict = self._convert_to_request_dict(
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\client.py", line 737, in _convert_to_request_dict
    api_params = self._emit_api_params(
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\client.py", line 766, in _emit_api_params
    self.meta.events.emit(
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\hooks.py", line 357, in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\hooks.py", line 228, in emit
    return self._emit(event_name, kwargs)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\hooks.py", line 211, in _emit
    response = handler(**kwargs)
  File "C:\Users\arund\Desktop\Code\Django\portfolio-project\venv\lib\site-packages\botocore\handlers.py", line 243, in validate_bucket_name
    raise ParamValidationError(report=error_msg)
botocore.exceptions.ParamValidationError: Parameter validation failed:
Invalid bucket name "": Bucket name must match the regex "^[a-zA-Z0-9.\-_]{1,255}$" or be an ARN matching the regex "^arn:(aws).*:(s3|s3-object-lambda):[a-z\-0-9]*:[0-9]{12}:accesspoint[/:][a-zA-Z0-9\-.]{1,63}$|^arn:(aws).*:s3-outposts:[a-z\-0-9]+:[0-9]{12}:outpost[/:][a-zA-Z0-9\-]{1,63}[/:]accesspoint[/:][a-zA-Z0-9\-]{1,63}$"

【问题讨论】:

  • 您不应该阻止存储类写入 S3 的错误,它只会警告您在项目中的某处有两个名为 user/main.css 的文件。 Collectstatic 从所有应用程序中获取所有静态文件,并将它们写入一个 static/ 文件夹,因此当您有两个文件时,一个在 application_1/static/user/main.css 中,一个在 application_2/static/user/main.css 中,它们都将在您的存储中转换为 static/user/main.css。但是,只会收集 first 文件,而忽略其他文件。这就是错误的含义。
  • 至于collectstatic为什么不起作用,它是在本地目录中收集文件吗?或者它根本没有收集任何东西。我唯一能想到的就是删除STATIC_ROOT(S3存储不使用它)
  • 删除 static_root 没有任何改变。它在运行时名称 staticfiles 上创建一个文件夹,该文件夹有一些相似之处。
  • 129 个静态文件复制到 'C:\Users\arund\Desktop\Code\Django\portfolio-project\staticfiles',409 个后处理。它也有这个。
  • 我认为您没有分享您的完整设置。您显示的目录包含 staticfiles.json,这意味着使用 ManifestStaticFilesStorage(S3Boto3Storage 和 StaticFilesStorage 不会创建 staticfiles.json 文件)。寻找 STATIC_ROOT 和 STATICFILES_STORAGE 的其他用法。

标签: django amazon-web-services heroku


【解决方案1】:

您的问题出在 django-heroku 包中。

Django-heroku 会覆盖您在 source code here 中看到的静态文件设置。

要禁用此功能,请将 django_heroku.settings(locals()) 更改为 django_heroku.settings(locals(), staticfiles=False)

这将保留您自己的静态文件设置。

【讨论】:

  • 我试过了,得到了以下结果。
  • 将AWS_STORAGE_BUCKET_NAME 和其他凭据环境变量添加到您的Heroku config in the dashboard
  • 它现在就在里面。
  • 好的,它在我的 aws 存储桶中创建了 2 个文件夹,其中包含 admin 和 user/main.css。关于 path('admin/', admin.site.urls) 的东西会创建它自己的文件夹。
  • 不,这是预期的行为。大多数应用程序的静态文件都在 static/ 中构建。见django's source code
猜你喜欢
  • 1970-01-01
  • 2017-10-22
  • 2015-08-13
  • 2012-10-10
  • 2013-05-08
  • 2017-04-20
  • 2021-11-01
  • 2015-06-05
  • 2012-05-06
相关资源
最近更新 更多