路径参数验证终极指南:系统自带 vs 自定义转换器
路径参数验证终极指南:系统自带 vs 自定义转换器
一、为什么需要验证
用户可以在浏览器地址栏随意输入:/shop/abc
、/product/xyz
。如果不加验证,视图直接拿字符串去查库,要么 404,要么 SQL 报错。因此路径参数必须“先过滤、后使用”。
二、两条技术路线
方式 | 位置 | 优点 | 缺点 |
---|---|---|---|
视图函数内正则 | views .py | 简单直观 | 代码重复,复用性差 |
自定义转换器 | urls .py | 全局复用,统一格式 | 需 3 步(定义-注册-使用) |
三、系统自带转换器速查
Django 内置 5 个,开箱即用:
-
int
:≥0 整数;path('item/<int:pk>/')
-
str
:除/
外任意字符(默认);path('slug/<str:title>/')
-
slug
:ASCII 字母、数字、连字符、下划线 -
uuid
:标准 UUID 格式 -
path
:可含/
的字符串,例如/2023/08/12/
使用规则:
path('shop/<int:city_id>/<int:shop_id>/', views.shop)
浏览器输入 /shop/11000/11005/
→ 视图收到 city_id=11000, shop_id=11005
;输入 /shop/abc/
直接 404。
四、自定义转换器 3 步曲
以“11 位手机号”为例:
1️⃣ 定义类
# book/converters.py
import re
from django.urls.converters import StringConverter
class MobileConverter(StringConverter):
regex = r'^1[3-9]\d{9}$' # 匹配 1 开头 11 位数字
def to_python(self, value):
return int(value) # 转成 int
def to_url(self, value):
return str(value) # 反向解析用
2️⃣ 注册
# book/urls.py
from django.urls import register_converter
from .converters import MobileConverter
register_converter(MobileConverter, 'mobile') # 别名 mobile
3️⃣ 使用
path('city/<int:city_id>/shop/<mobile:phone>/', views.shop_by_phone)
效果:
-
/city/1100/shop/13312341234/
→ 视图收到city_id=1100, phone=13312341234
-
/city/1100/shop/123/
→ 404(正则不匹配)
五、完整示例:手机号 + 城市
# urls.py
from django.urls import path, register_converter
from book import views, converters
register_converter(converters.MobileConverter, 'mobile')
urlpatterns = [
path('shop/<int:city_id>/<mobile:phone>/', views.shop_detail),
]
# views.py
def shop_detail(request, city_id, phone):
try:
shop = Shop.objects.get(city_id=city_id, phone=phone)
return HttpResponse(f"{shop.name} 欢迎你!")
except Shop.DoesNotExist:
return HttpResponse("门店不存在", status=404)
六、常见问题 FAQ
-
404 还是 500?
转换器不匹配 → 404;匹配后视图逻辑错误 → 500。 -
顺序要求
register_converter
必须放在urlpatterns
之前,否则启动时报Invalid converter
。 -
反向解析
reverse('shop', args=[1100, 13312341234])
自动用to_url
方法生成正确 URL。 -
复用场景
多个 APP 共享手机号、身份证号、统一社会信用代码等格式,都可写成独立转换器,一处注册,全局使用。
七、调试技巧
在视图里打印参数类型:
print(type(city_id), city_id, type(phone), phone)
确认转换器生效后,再进行后续业务逻辑。
八、一句话总结
“路径参数先过滤、后使用;内置转换器够用就用,不够用就自定义三步:定义类 → 注册 → 路由 <转换器:变量>
。”
- 点赞
- 收藏
- 关注作者
评论(0)