You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:18:19