Django3.1点击密码重置链接触发AssertionError报错求助
问题排查与解决方案
问题根因
1. AssertionError报错根因
Django 3.1版本的PasswordResetConfirmView默认要求路由传递uidb64参数,你当前urls.py中路由的命名分组为uidb36,同时邮件模板中调用url时也传递的是uidb36参数,视图无法获取到预期的uidb64参数,触发断言失败。
2. 请求域名被替换为django:8000根因
你使用Nginx做反向代理,请求转发到Django容器时没有正确传递原始请求的Host头,Django默认读取到的Host是Docker Compose内部的服务名django:8000,导致跳转/生成链接时使用了内部服务域名。
修复步骤
1. 修复密码重置路由与模板参数
- 修改urls.py中的路由配置,将
uidb36替换为uidb64:
auth_patterns = [ path('password_reset/', auth_views.PasswordResetView.as_view(), name='password_reset'), re_path(r'^password_reset/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), ]
- 修改
password_reset_email.html中的url调用参数,将uidb36=uid替换为uidb64=uid:
{% url 'password_reset_confirm' uidb64=uid token=token %}
如果你仍需要使用uidb36格式,可以在初始化视图时指定参数名:
auth_views.PasswordResetConfirmView.as_view(uidb_url_kwarg='uidb36')
2. 修复反向代理域名传递问题
- 首先修改Nginx的转发配置,在转发到django服务的location块中添加以下头传递配置:
location / { proxy_pass http://django:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
- 修改Django的
settings.py配置,添加以下参数:
# 允许读取反向代理传递的Host头 USE_X_FORWARDED_HOST = True # 识别HTTPS协议 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 替换为实际部署的域名,本地测试可填['localhost', '127.0.0.1'] ALLOWED_HOSTS = ['你的实际访问域名']
内容的提问来源于stack exchange,提问作者Matthew Marshall
相关产品推荐
相关产品推荐

