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

cPanel Passenger部署Django时静态文件返回404错误如何解决

cPanel Passenger部署Django静态文件404排查方案

从报错日志Not Found: /home/mysite/public_html/build/static/admin/css/base.css可以直接定位核心问题:当前静态资源请求没有被Apache直接接管,而是全部透传给了Django应用,Django路由仅匹配Web请求路径,不会直接读取磁盘绝对路径,因此触发404。按以下步骤逐一排查修复:

  • 第一步:配置.htaccess静态文件直出规则
    cPanel的Passenger默认会把所有请求转发给Django处理,需要在网站根目录(一般是public_html目录)下的.htaccess文件中,把静态、媒体文件的规则写在Passenger规则的最前面,让Apache直接响应这类请求,不要转给应用:

    # 静态文件直出规则
    Alias /static /home/mysite/public_html/build/static
    <Directory /home/mysite/public_html/build/static>
        Require all granted
    </Directory>
    
    # 媒体文件直出规则
    Alias /media /home/mysite/public_html/build/media
    <Directory /home/mysite/public_html/build/media>
        Require all granted
    </Directory>
    
    # 下面保留原有的Passenger相关规则即可
    

    注意:规则顺序不能乱,静态规则必须放在Passenger转发规则之前,否则配置不生效。

  • 第二步:核对静态路径配置和实际路径一致
    你当前settings.py里用相对路径拼接STATIC_ROOT,很可能因为BASE_DIR计算偏差导致路径不匹配,先进入项目虚拟环境执行以下命令确认实际生效的静态根路径:

    python manage.py shell -c "from django.conf import settings; print(settings.STATIC_ROOT)"
    

    如果输出的路径和你实际存放静态文件的/home/mysite/public_html/build/static不一致,直接把STATIC_ROOT改成绝对路径即可,避免相对路径计算错误:

    STATIC_ROOT = "/home/mysite/public_html/build/static"
    MEDIA_ROOT = "/home/mysite/public_html/build/media"
    STATIC_URL = "/static/"
    MEDIA_URL = "/media/"
    

    改完之后重新执行python manage.py collectstatic --noinput,确认所有静态文件都被收集到对应目录。

  • 第三步:修正Passenger路径修复逻辑
    自定义的PassengerPathInfoFix如果配置错误,会把磁盘路径错误写入请求的PATH_INFO参数,导致Django路由匹配异常,替换为以下经过验证的passenger_wsgi.py内容即可:

    import os
    import sys
    from django.core.wsgi import get_wsgi_application
    
    # 把项目根目录加入Python导入路径
    sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "替换为你的项目名.settings")
    
    # Passenger路径修复中间件
    class PassengerPathInfoFix:
        def __init__(self, app):
            self.app = app
        def __call__(self, environ, start_response):
            from urllib.parse import unquote
            environ["SCRIPT_NAME"] = ""
            request_uri = unquote(environ.get("REQUEST_URI", ""))
            path_info = unquote(environ.get("PATH_INFO", ""))
            if request_uri.startswith(path_info):
                environ["PATH_INFO"] = request_uri.split("?", 1)[0]
            return self.app(environ, start_response)
    
    application = get_wsgi_application()
    application = PassengerPathInfoFix(application)
    
  • 第四步:权限与重启验证
    配置修改完成后,先重启Passenger应用:可以在cPanel的Python应用管理界面点重启,也可以在项目目录执行touch tmp/restart.txt触发自动重启。
    之后检查目录权限:static和media目录权限设为755,内部文件权限设为644,保证Apache运行用户有读取权限。
    最后清除浏览器缓存,直接访问你的域名/static/admin/css/base.css验证是否能正常加载CSS文件。

补充说明:生产环境(DEBUG=False)下Django默认不会托管静态文件,不要依赖Django本身响应静态资源,不仅性能差,也容易出现各类路径问题,必须通过Web服务器(Apache/Nginx)直接托管静态文件。如果是临时调试需要用Django自带静态服务,可以在根urls.py中追加以下配置,该配置仅在DEBUG=True时生效:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # 原有路由配置
]
if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:18:14