allowed_hosts为空或配置错误时,django在debug=false下直接返回disallowedhost错误,提示“invalid http_host header”,因host头未完全匹配列表中任一值;必须显式列出域名/ip(含www、端口等),禁用通配符,推荐环境变量动态配置并校验。

ALLOWED_HOSTS 为空或配置错误时的典型报错
访问 Django 项目直接返回 DisallowedHost 错误页面,控制台或日志里出现类似 Invalid HTTP_HOST header: 'example.com' 的提示——这说明请求的 Host 头没被 ALLOWED_HOSTS 接收,Django 主动拒绝了该请求。
根本原因不是“域名没加”,而是:Django 在 DEBUG=False 时强制校验 Host 请求头,且只认 ALLOWED_HOSTS 中**完全匹配**或带通配符的条目。空列表、仅写 '*'(开发环境外不推荐)、漏掉端口、大小写/协议混淆,都会触发此错。
-
ALLOWED_HOSTS = []:生产环境等同于“拒绝所有”,哪怕你用127.0.0.1:8000访问也会失败 -
ALLOWED_HOSTS = ['*']:仅允许在DEBUG=True下工作;DEBUG=False时 Django 会忽略它并报错 - 写了
'example.com'却用www.example.com或https://example.com访问:Django 不解析协议、不自动补 www,必须显式列出
生产环境必须显式列出域名(含 www 和裸域)
不能依赖通配符,也不能靠 Nginx/Apache 转发后就以为 Host 头“安全”。Django 的校验发生在 WSGI 层,早于反向代理的 Host 重写逻辑——所以你看到的 Host 头,是客户端发来的原始值,不是代理后改过的。
比如用户通过 https://www.example.com 访问,Nginx 转发给 Django 时若未设置 proxy_set_header Host $host;,Django 收到的可能是 localhost:8000 或空值;反之如果设置了但没在 ALLOWED_HOSTS 里加 'www.example.com',照样报错。
- 正确写法示例(生产 settings.py):
ALLOWED_HOSTS = [ 'example.com', 'www.example.com', 'api.example.com', '192.168.1.100', # 如果内网有固定 IP 访问 ] - 不要写
'https://example.com':协议不参与匹配,只校验 Host 部分 - 本地开发可保留
['localhost', '127.0.0.1', '[::1]'],但务必确认DEBUG=True
带端口的开发场景要明确写出端口号
用 python manage.py runserver 0.0.0.0:8001 启动,然后浏览器访问 http://localhost:8001,Django 收到的 Host 是 localhost:8001,不是 localhost。如果 ALLOWED_HOSTS 只写了 'localhost',就会报错。
- 开发时带端口访问,必须把端口一起写进列表:
['localhost:8001', '127.0.0.1:8001'] - 使用
[::1](IPv6 回环)时也需加端口:'[::1]:8001' - 如果用 Docker 或云服务器,外部 IP + 端口也要列全,例如:
'203.0.113.45:8000'
环境变量驱动配置更安全,避免硬编码
把域名写死在 settings.py 里,容易导致测试/预发/生产环境混用,或者 Git 提交敏感配置。建议从环境变量读取,并做基本校验。
提供使用 django-unfold (v0.56+) 构建高级 Django 管理界面的专业指导。当用户提及 django-unfold、unfold admin 等内容时使用此技能。
示例(放在 settings.py 底部):
import os
from django.core.exceptions import ImproperlyConfigured
<p>allowed_hosts_env = os.environ.get('DJANGO_ALLOWED_HOSTS')
if not allowed_hosts_env:
raise ImproperlyConfigured('DJANGO_ALLOWED_HOSTS environment variable is required')</p><p>ALLOWED_HOSTS = [host.strip() for host in allowed_hosts_env.split(',')] </p>
启动时传入:DJANGO_ALLOWED_HOSTS="example.com,www.example.com" gunicorn myproject.wsgi。这样既解耦又便于 CI/CD 切换。
注意:环境变量值里不能有空格,逗号分隔即可;Docker Compose 中用 environment: 字段注入,K8s 用 ConfigMap 或 Secret。
最常被忽略的是:Nginx 的 proxy_set_header Host $host; 是否启用,以及 ALLOWED_HOSTS 是否随部署环境动态加载——这两处任一出错,都可能导致看似配置对了,但依然报 DisallowedHost。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










