Django3.2中如何让re_path向视图返回值为None的关键字参数
解决方案
你遇到的问题确实是Django 3.0版本的官方变更导致的:
RegexPattern(re_path()底层使用的组件)对于缺失的可选命名组,不再将值为None的关键字参数传递给视图。
Django 2.2及更早版本中可选分组未命中时会自动向self.kwargs塞入值为None的对应键,升级后该逻辑默认移除,所以直接访问不存在的键会触发KeyError。以下是三种可实现旧版本逻辑的方案:
方案1:修改视图参数获取逻辑(改动最小,适合小项目)
直接将字典键访问改为get()方法,显式指定默认值为None,和旧版本行为完全一致:
# 旧写法(会触发KeyError) param = self.kwargs['param'] # 新写法 param = self.kwargs.get('param', None)
方案2:路由层指定默认参数(适合路由数量中等的项目)
在re_path定义时通过kwargs参数显式指定可选分组的默认值为None:
# urls.py from django.urls import re_path from . import views urlpatterns = [ # 括号加?代表param是可选分组,显式指定默认值为None re_path(r'^test/(?P<param>\w+)?$', views.TestView.as_view(), kwargs={'param': None}, name='test'), ]
配置后即使URL未传递param参数,视图的self.kwargs中也会存在param键,值为None。
方案3:自定义兼容版re_path(适合大项目、老代码多的场景)
如果项目中存在大量用到可选分组的re_path路由,逐个修改视图或路由成本过高,可以自定义一个兼容旧版本逻辑的re_path函数,全局替换原生实现:
# utils/urls.py import re from django.urls import re_path as original_re_path def re_path(regex, view, kwargs=None, name=None): kwargs = kwargs or {} # 提取正则中所有可选命名分组 pattern = re.compile(regex) for group_name in pattern.groupindex.keys(): # 判断分组是否为可选格式 group_pattern = regex.split(f'(?P<{group_name}>')[1] if group_pattern.startswith('?') or (')?' in group_pattern): kwargs.setdefault(group_name, None) return original_re_path(regex, view, kwargs=kwargs, name=name)
之后将项目所有urls.py中导入re_path的语句改为从上述工具文件导入即可,无需修改业务代码即可恢复旧版本行为。
内容的提问来源于stack exchange,提问作者Somraj Chowdhury
相关产品推荐
相关产品推荐

