如何在Namecheap上以ASGI模式部署Django并解决报错问题
解决Namecheap上Django ASGI应用部署的Passenger报错问题
报错原因
Passenger是WSGI协议的服务器,而你导入的是Django的ASGI应用——两者的调用接口不兼容:WSGI应用的__call__方法接收environ和start_response两个参数,ASGI应用的__call__则需要scope、receive、send三个参数,这就是触发TypeError: __call__() missing 1 required positional argument: 'send'的核心原因。
解决步骤(不切换WSGI模式)
1. 安装ASGI转WSGI适配器库
在项目的虚拟环境中执行以下命令安装asgiref:
pip install asgiref
2. 修改passenger_wsgi.py文件
重点添加ASGI到WSGI的转换逻辑,修改后的完整代码如下:
import os import sys import django sys.path.append(os.getcwd()) os.environ['DJANGO_SETTINGS_MODULE'] = 'website.settings.development' django.setup() SCRIPT_NAME = os.getcwd() print("Script name: ", SCRIPT_NAME) class PassengerPathInfoFix(object): """ Sets PATH_INFO from REQUEST_URI because Passenger doesn't provide it. """ def __init__(self, app): self.app = app print("Start Init") print("App is: ", self.app) print("End Init") def __call__(self, environ, start_response): from urllib.parse import unquote print("Start Calling") environ['SCRIPT_NAME'] = SCRIPT_NAME request_uri = unquote(environ['REQUEST_URI']) script_name = unquote(environ.get('SCRIPT_NAME', '')) offset = request_uri.startswith(script_name) and len(environ['SCRIPT_NAME']) or 0 environ['PATH_INFO'] = request_uri[offset:].split('?', 1)[0] return self.app(environ, start_response) # Get ASGI application from website.routing import application # 导入ASGI转WSGI的适配器 from asgiref.wsgi import ASGIToWSGI # 将ASGI应用转换为WSGI兼容的应用 wsgi_application = ASGIToWSGI(application) print("Before calling application") # 用PathInfoFix包装转换后的WSGI应用 application = PassengerPathInfoFix(wsgi_application)
3. 验证部署
修改完成后,Namecheap的Passenger通常会自动检测文件变化并重启服务;若未自动重启,可通过主机控制面板手动触发服务重启,之后访问网站即可验证是否正常运行。
额外注意事项
- 确保Passenger使用的是安装了
asgiref的项目虚拟环境; - 若你的Django版本低于3.0,ASGI支持存在兼容性问题,建议升级至Django 3.0及以上版本。
内容的提问来源于stack exchange,提问作者Abdelhamed Abdin
相关产品推荐
相关产品推荐

