<int:id>自动转整数传参,无需手动转换,但仅处理路径段,不涉及查询参数或表单数据;参数名须与视图函数一致;非纯数字路径返回404;查库推荐get_object_or_404防500;模板用{% url %}反向解析,勿硬编码;调试可查Debug页面“Resolved URL”。

URL路由里用<int:id>能直接拿到整数,但别忘了它只是路径的一部分
Django的URL捕获机制会自动把<int:id>转成整数传给视图函数,不需要手动int()转换。但它只负责从路径段提取,不处理查询参数(比如?page=2)或表单数据。
- 路径变量必须和视图函数参数名完全一致:如果URL写
<int:post_id>,函数签名就得是def detail(request, post_id): -
<int:xxx>只接受纯数字字符串,/article/123a/会直接404,不会进视图 - 如果需要可选参数(比如
/user/123/edit/和/user/123/共用一个视图),得在URL中定义两个pattern,或用<path:rest>兜底
视图里怎么安全用这个id查数据库
拿到id后别直接塞进filter(id=id)就完事——Django ORM虽然防SQL注入,但没防逻辑错误。最常见的是查不到对象时抛DoesNotExist异常,导致500。
- 用
get_object_or_404(MyModel, id=id)代替MyModel.objects.get(id=id),自动返回404而不是崩溃 - 如果允许
id为0或负数,而你的模型主键是AutoField,默认从1开始,那id=0也会404——这不是bug,是预期行为 - 注意
id类型:<int:id>保证是int,但数据库字段如果是BigAutoField,Python int也能正常处理,不用额外转
模板里反向生成带id的URL,别拼字符串
硬编码/article/{{ article.id }}/看着快,但一旦URL pattern改了(比如从article/<int:id>/变成post/<int:pk>/),所有模板全得改。
- 一律用
{% url 'article_detail' id=article.id %},name要和urls.py里name=参数一致 - 如果URL定义的是
<int:pk>,模板里就得写pk=article.id,名字不匹配会报NoReverseMatch - 传多个参数时顺序无关,但每个关键字必须存在,比如
{% url 'user_profile' user_id=123 tab='posts' %},缺一个就失败
调试时怎么看id到底有没有被正确捕获
最直接的办法不是翻文档,是在视图开头加一行print(type(id), id),看终端输出。但更靠谱的是看Django debug page里的“Resolved URL”部分——它会明确写出匹配到哪个pattern、各组参数值是什么。
- 如果debug page显示
Resolved URL: None,说明根本没匹配上任何pattern,检查URL是否带尾部斜杠、是否和APPEND_SLASH设置冲突 - 如果看到
id是字符串(比如'123'),说明你没用<int:id>,而是用了<str:id>或默认的<slug:id> - 用
python manage.py show_urls(需装django-extensions)能快速列出所有注册的URL及其参数类型,比手翻urls.py快得多
真正容易被忽略的点是:路径变量和查询参数混用时,很多人以为request.GET.get('id')能覆盖<int:id>,其实不能——它们是两套独立机制,一个在路径里,一个在?后面,别指望自动合并。










