为何Django中Request.build_absolute_uri返回localhost而非真实域名?
解决Django+Nginx反向代理下build_absolute_uri指向localhost的问题
问题根源是Nginx作为反向代理时,Django收到的请求来自WSGI服务器(Waitress/Gunicorn)的localhost端口,默认会用这个地址生成绝对链接。要让Django获取真实的域名和协议,需要从Nginx传递正确的请求头,同时配置Django信任这些头。
步骤1:配置Nginx传递请求头
在你的Nginx站点配置的location /块中,添加以下proxy_set_header指令,把真实的请求信息传递给Django:
location / { proxy_pass http://localhost:8080; # 传递请求使用的协议(http/https) proxy_set_header X-Forwarded-Proto $scheme; # 传递真实的域名(含端口,如果用了非标准端口) proxy_set_header X-Forwarded-Host $host; # 传递原始请求的Host头 proxy_set_header Host $host; # 传递客户端真实IP(可选,但推荐) proxy_set_header X-Forwarded-For $remote_addr; }
修改完成后重启Nginx:sudo systemctl restart nginx
步骤2:配置Django信任代理头
在项目的settings.py中修改以下配置:
- 开启使用X-Forwarded-Host头:
USE_X_FORWARDED_HOST = True
- 配置HTTPS代理头(如果你的站点用HTTPS):
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
- 添加真实域名到ALLOWED_HOSTS:
ALLOWED_HOSTS = ['example.com', '你的服务器IP'] # 替换成你的真实域名和IP
- 如果你的Nginx使用了非标准端口(比如8080以外的公网端口),还可以开启:
USE_X_FORWARDED_PORT = True
步骤3:配置WSGI服务器(针对Waitress)
如果用的是Waitress,需要设置信任来自Nginx的代理请求,否则它会忽略X-Forwarded-*头。启动Waitress时加上--trusted-proxy参数:
waitress-serve --trusted-proxy 127.0.0.1 your_project.wsgi:application
如果是用配置文件启动Waitress,添加:
trusted_proxies = ['127.0.0.1']
Gunicorn默认不需要额外配置,只要Nginx传递了头、Django配置正确就能生效。
验证
重启你的WSGI服务器(Gunicorn/Waitress)和Nginx后,测试request.build_absolute_uri()或request._current_scheme_host,应该会返回真实的域名和协议,无需再硬编码地址。
内容的提问来源于stack exchange,提问作者Somebody
相关产品推荐
相关产品推荐

