Django文章详情页点击分类跳转触发id期望数字报错解决方案
问题根因
导航栏所有链接用的是不带前导斜杠的相对路径,浏览器解析这类路径时会基于当前所在页面的路径做拼接:
- 在首页(路径为
/)点击href="politics",最终拼接结果是/politics,刚好匹配分类列表的路由,所以跳转正常 - 在文章详情页(路径为
/post/xxx)点击同一个链接,最终会拼成/post/politics,优先匹配到path('post/<str:pk>', views.post, name='post')这条路由,把字符串politics当成文章主键id传给post视图。视图里执行Post.objects.get(id=pk)时,id字段要求传入数字类型,拿到字符串直接触发类型错误。
修复方法
两种方案选其一即可,优先推荐第二种,符合Django开发规范,后续维护更方便。
方案1:修改为根路径绝对路径
给所有导航链接的href值前面加前导斜杠/,强制浏览器从站点根目录开始解析路径,不会再基于当前子路径拼接。修改后的导航栏代码:
<nav id="navbar" class="navbar"> <ul> <li><a href="/about">About</a></li> <li><a href="/guestposting">Guest Posting</a></li> <li class="dropdown"> <a href=""><span>Categories</span> <i class="bi bi-chevron-down dropdown-indicator"></i></a> <ul> <li><a href="/tech">Tech</a></li> <li><a href="/bizconomics">Bizconomics</a></li> <li><a href="/politics">Politics</a></li> <li><a href="/religion">Religion</a></li> <li><a href="/sports">Sports</a></li> </ul> </li> <li><a href="/contactform">Contact</a></li> </ul> </nav>
改完后任意页面点击导航链接,都会直接跳转到根路径下的对应地址,不会再拼接到/post/路径下。
方案2:使用Django原生url反向解析(推荐)
不要在模板里硬编码路径,用Django内置的{% url %}模板标签,根据路由的name属性自动生成正确的绝对路径。后续就算调整路由的实际路径,只要name不变,模板里的链接不需要批量修改。修改后的导航栏代码:
<nav id="navbar" class="navbar"> <ul> <li><a href="{% url 'about' %}">About</a></li> <li><a href="{% url 'guestposting' %}">Guest Posting</a></li> <li class="dropdown"> <a href=""><span>Categories</span> <i class="bi bi-chevron-down dropdown-indicator"></i></a> <ul> <li><a href="{% url 'tech' %}">Tech</a></li> <li><a href="{% url 'bizconomics' %}">Bizconomics</a></li> <li><a href="{% url 'politics' %}">Politics</a></li> <li><a href="{% url 'religion' %}">Religion</a></li> <li><a href="{% url 'sports' %}">Sports</a></li> </ul> </li> <li><a href="{% url 'contactform' %}">Contact</a></li> </ul> </nav>
这种写法会在模板渲染时直接生成正确的全路径,完全不会出现相对路径拼接错误的问题。
额外优化建议
当前post视图直接用Post.objects.get(id=pk)查询文章,遇到非法pk(比如不存在的id、非数字参数)会直接抛出500服务器错误,建议改成Django内置的快捷方法做404处理:
from django.shortcuts import get_object_or_404 def post(request, pk): posts = get_object_or_404(Post, id=pk) return render(request, 'posts.html', {'posts':posts})
修改后遇到非法参数会正常返回404页面,不会直接暴露服务器错误。
内容的提问来源于stack exchange,提问作者Felicity
相关产品推荐
相关产品推荐

