为何Django URL正则的(?P<topic_id>\d+)在Python re中无法通过topic_id取值?
为什么用
re.findall()无法通过命名组名获取匹配值? 我来帮你理清这个问题~
首先,你得先搞清楚re.findall()和Django路由解析背后用的正则方法的核心差异:
re.findall()的行为逻辑:这个方法的设计目标是批量提取所有匹配的内容。当正则表达式里包含捕获组(不管是命名组还是匿名组)时,它只会返回捕获到的字符串值的列表(如果有多个捕获组,会返回元组的列表),不会返回带有命名组属性的匹配对象。所以你拿到的['1']只是一个普通的字符串列表,自然没有.topic_id这个属性。Django路由的工作方式:Django内部处理URL匹配时,用的是
re.match()或者re.search()这类方法,它们返回的是一个Match对象。这个对象会完整保留命名组的匹配信息,你可以通过.group('topic_id')或者.groupdict()来获取对应的参数值——这也是Django能把topic_id正确传递给视图函数的原因。
如果你想验证命名组的匹配效果,应该用re.search()或者re.finditer(),而不是findall:
用re.search()验证的示例:
import re # 获取匹配对象 match_result = re.search(r'topics/(?P<topic_id>\d+)/$', "topics/1/") if match_result: # 通过命名组名称获取匹配值 print(match_result.group('topic_id')) # 输出:'1' # 或者获取所有命名组的键值对字典 print(match_result.groupdict()) # 输出:{'topic_id': '1'}
用re.finditer()批量处理多匹配项的示例:
如果有多个符合规则的URL片段,可以用finditer()返回匹配对象的迭代器,逐个处理:
import re for match_obj in re.finditer(r'topics/(?P<topic_id>\d+)/$', "topics/1/topics/2/"): print(match_obj.group('topic_id')) # 依次输出'1'和'2'
简单总结一下:你之前用findall只是拿到了匹配的字符串值,但丢失了命名组的上下文信息;而Django用的是能完整保留匹配上下文的方法,所以能正确提取并传递命名参数。
内容的提问来源于stack exchange,提问作者Wizard
相关产品推荐
相关产品推荐

