Django执行collectstatic报错:TypeError: 期望str实例,得到NoneType
问题描述
本地环境下项目静态文件加载正常,部署到Heroku时按指引将数据库迁移至AWS RDS(PostgreSQL已正常可用,能创建用户),但配置S3存储桶后遇到以下问题:
- 手动复制静态文件到S3,出现“failed to load the resources”错误
- 执行
python manage.py collectstatic上传静态文件到S3,持续报错:TypeError: sequence item 0: expected str instance, NoneType found - 手动上传静态文件后,尝试上传头像也触发相同错误
settings.py 配置
""" Django settings for fcap project. Generated by 'django-admin startproject' using Django 4.1. For more information on this file, see https://docs.djangoproject.com/en/4.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.1/ref/settings/ """ from pathlib import Path import os from django.contrib.messages import constants as messages # 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/4.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'django-insecure-(c&774q+skzfb=n499li8!!!jv_m&s65eli3#w&zl+%c8h%sb$' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] MESSAGE_TAGS = { messages.DEBUG: 'alert-info', messages.INFO: 'alert-info', messages.SUCCESS: 'alert-success', messages.WARNING: 'alert-warning', messages.ERROR: 'alert-danger', } # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'fcap_users', 'rest_framework', 'storages', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'fcap.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 = 'fcap.wsgi.application' # Database # https://docs.djangoproject.com/en/4.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'fcap_db', 'USER': 'asad_hussain', 'PASSWORD': '(hidden for purpose)', 'HOST': 'database-2.cfhvhdusomqt.us-east-1.rds.amazonaws.com', 'PORT': '5432', } } # Password validation # https://docs.djangoproject.com/en/4.1/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/4.1/howto/deployment/checklist/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [os.path.join(BASE_DIR, 'fcap/static')] STATIC_ROOT = os.path.join(BASE_DIR, 'static') MEDIA_URL = "/images/" MEDIA_ROOT = os.path.join(BASE_DIR, 'static/images') # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # S3 Bucket Config AWS_KEY_ACCESS_KEY_ID = '(hidden)' AWS_SECRET_ACCESS_KEY = '(hidden)' AWS_STORAGE_BUCKET_NAME = 'asad-hussain-fcap' AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = None DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' AWS_S3_ADDRESSING_STYLE = "virtual"
requirements.txt 依赖
asgiref==3.5.2 boto3==1.24.50 botocore==1.27.50 Django==4.1 django-filter==22.1 django-storages==1.13.1 djangorestframework==3.13.1 jmespath==1.0.1 Markdown==3.4.1 multielo==0.4.1 numpy==1.23.1 pandas==1.4.3 Pillow==9.2.0 psycopg2==2.9.3 python-dateutil==2.8.2 pytz==2022.1 s3transfer==0.6.0 six==1.16.0 sqlparse==0.4.2 tzdata==2022.1 urllib3==1.26.11 validate-email==1.3
项目文件结构

解决方案
1. 修正S3配置变量名错误
settings.py里的AWS密钥变量名写错了,正确变量名是AWS_ACCESS_KEY_ID,原配置写成了AWS_KEY_ACCESS_KEY_ID,导致boto3无法获取有效密钥,触发NoneType错误。修改后:
# S3 Bucket Config AWS_ACCESS_KEY_ID = '(你的实际密钥)' AWS_SECRET_ACCESS_KEY = '(你的实际密钥)' AWS_STORAGE_BUCKET_NAME = 'asad-hussain-fcap' AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = None DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' AWS_S3_ADDRESSING_STYLE = "virtual"
2. 补充S3区域配置
缺少区域配置会导致请求地址错误,添加对应RDS的区域配置:
AWS_S3_REGION_NAME = 'us-east-1' # 与你的RDS区域保持一致
3. 配置STATIC/MEDIA_URL指向S3
使用S3存储静态文件时,需将资源地址指向S3存储桶:
STATIC_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/' MEDIA_URL = f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/images/'
4. 重新执行collectstatic
修正配置后,运行命令上传静态文件:
python manage.py collectstatic --noinput
5. 检查S3权限与CORS
- 确保IAM用户拥有
s3:PutObject、s3:GetObject等必要权限 - 配置S3存储桶CORS规则,允许Heroku域名访问资源
6. 生产环境配置调整
部署到Heroku时,需关闭DEBUG模式并添加允许访问的域名:
DEBUG = False ALLOWED_HOSTS = ['你的Heroku应用域名.herokuapp.com']
内容的提问来源于stack exchange,提问作者Asad Hussain
相关产品推荐
相关产品推荐

