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

关闭Debug后Django项目触发TypeError的问题求助

Django Debug=False时触发TypeError问题排查与解决

一直用Debug模式运行Django项目,切换为Debug=False后抛出错误:

TypeError: expected str, bytes or os.PathLike object, not NoneType

进一步排查发现,admin/js/jquery.js对应的absolute_path变量值为None。

整理的关键线索:

  • 问题根源在django-cloudinary-storage库中;
  • 大概率是执行python manage.py collectstatic命令后出现的(此前从未执行过该命令);
  • Debug=True时项目运行完全正常,仅关闭Debug模式时触发错误。

相关配置片段(settings.py)

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') 
STATICFILES_DIRS = ( 
    os.path.join(BASE_DIR, 'static'),
)
STATICFILES_STORAGE = 'cloudinary_storage.storage.StaticHashedCloudinaryStorage'

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

完整错误栈(Traceback)

Traceback (most recent call last):
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 910, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 157, in inner_run
    handler = self.get_handler(*args, **options)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/contrib/staticfiles/management/commands/runserver.py", line 31, in get_handler
    handler = super().get_handler(*args, **options)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 78, in get_handler
    return get_internal_wsgi_application()
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/servers/basehttp.py", line 47, in get_internal_wsgi_application
    return import_string(app_path)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/utils/module_loading.py", line 30, in import_string
    return cached_import(module_path, class_name)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/utils/module_loading.py", line 15, in cached_import
    import_module(module_path)
  File "/opt/homebrew/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/Users/ryanoh/Projects/crystalize/crystalize/wsgi.py", line 16, in <module>
    application = get_wsgi_application()
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/wsgi.py", line 13, in get_wsgi_application
    return WSGIHandler()
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/handlers/wsgi.py", line 126, in __init__
    self.load_middleware()
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/core/handlers/base.py", line 61, in load_middleware
    mw_instance = middleware(adapted_handler)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/middleware.py", line 51, in __init__
    self.add_files(self.static_root, prefix=self.static_prefix)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/base.py", line 113, in add_files
    self.update_files_dictionary(root, prefix)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/base.py", line 125, in update_files_dictionary
    self.add_file_to_dictionary(url, path, stat_cache=stat_cache)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/base.py", line 136, in add_file_to_dictionary
    static_file = self.get_static_file(path, url, stat_cache=stat_cache)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/base.py", line 210, in get_static_file
    self.add_cache_headers(headers, path, url)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/base.py", line 231, in add_cache_headers
    if self.immutable_file_test(path, url):
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/middleware.py", line 146, in immutable_file_test
    static_url = self.get_static_url(name_without_hash)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/whitenoise/middleware.py", line 169, in get_static_url
    return decode_if_byte_string(staticfiles_storage.url(name))
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/contrib/staticfiles/storage.py", line 166, in url
    return self._url(self.stored_name, name, force)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/contrib/staticfiles/storage.py", line 145, in _url
    hashed_name = hashed_name_func(*args)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/django/contrib/staticfiles/storage.py", line 394, in stored_name
    self.hashed_name(name, content=None, filename=intermediate_name)
  File "/Users/ryanoh/Projects/crysenv/lib/python3.9/site-packages/cloudinary_storage/storage.py", line 286, in hashed_name
    content = open(absolute_path, 'rb')
TypeError: expected str, bytes or os.PathLike object, not NoneType

问题原因分析

当Debug=False时,Django不再自动提供静态文件服务,转而依赖已收集的静态文件或第三方存储服务。这里的矛盾点在于:

  1. StaticHashedCloudinaryStorage会将静态文件上传到Cloudinary远程存储,本地并不会保留这些文件的副本(或者collectstatic后本地的文件结构和存储期望的不匹配);
  2. Whitenoise中间件在初始化时会扫描本地静态文件目录,尝试为文件添加缓存头,当它处理到已上传到Cloudinary的文件(比如admin的jquery.js)时,会调用存储的url方法生成哈希文件名,但django-cloudinary-storage在计算哈希时需要读取本地文件,此时本地找不到对应文件,导致absolute_path为None,触发打开文件的TypeError。

解决方法

方法1:替换为非哈希版本的Cloudinary存储

将STATICFILES_STORAGE改为不带哈希的版本,避免计算哈希时需要读取本地文件:

STATICFILES_STORAGE = 'cloudinary_storage.storage.StaticCloudinaryStorage'

这种方法简单直接,但失去了静态文件哈希缓存的优势,需要手动处理缓存刷新。

方法2:让Admin静态文件使用本地存储

通过自定义存储后端,让Django Admin的静态文件不使用Cloudinary,而是保留在本地:

import os
from django.contrib.staticfiles.storage import StaticFilesStorage
from cloudinary_storage.storage import StaticHashedCloudinaryStorage
from django.conf import settings

class AdminStaticStorage(StaticFilesStorage):
    def __init__(self, *args, **kwargs):
        kwargs['location'] = os.path.join(settings.STATIC_ROOT, 'admin')
        super().__init__(*args, **kwargs)

# 配置静态文件存储映射
STATICFILES_STORAGES = {
    'default': {
        'BACKEND': 'cloudinary_storage.storage.StaticHashedCloudinaryStorage',
    },
    'admin': {
        'BACKEND': 'your_project.settings.AdminStaticStorage',
        'LOCATION': 'static/admin/',
    }
}

同时需要确保collectstatic时将Admin的静态文件收集到本地目录。

方法3:禁用Whitenoise的Immutable文件检测

修改Whitenoise的配置,跳过对Cloudinary存储文件的缓存头检测:

WHITENOISE_IMMUTABLE_FILE_TEST = lambda path, url: False

这种方法会关闭所有文件的永久缓存检测,可能影响缓存效率,但能快速解决当前错误。

方法4:确保本地保留静态文件副本

执行collectstatic时添加--no-post-process参数,避免Cloudinary存储删除本地文件:

python manage.py collectstatic --no-post-process

这样本地STATIC_ROOT目录会保留所有静态文件的副本,django-cloudinary-storage就能找到absolute_path计算哈希了。不过这种方法会占用本地存储空间,且需要同步本地和Cloudinary的文件版本。

内容的提问来源于stack exchange,提问作者RyanOh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:30:52