Django中两条结构相同的slug路由匹配错误视图该如何解决?
问题原因解释
Django的路由匹配规则是从上到下顺序匹配,只要找到第一个符合模式的路由就会停止匹配。你最初的两个路由路径模式完全一致,都是<slug:title>/,所以所有请求都会匹配到排在前面的news_read视图,后面的movie_read永远不会被触发,这就是渲染错误模板的根本原因。
更优的解决方案
- 方案1:调整URL结构,把分类标识放在slug前
这是最推荐的方案,符合绝大多数站点的URL设计规范,语义清晰对SEO也更友好,路由配置修改为:
path('news/<slug:title>/',views.news_read,name="news_read"), path('movie/<slug:title>/',views.movie_read,name="movie_read"),
最终生成的URL格式为/news/xxx/、/movie/xxx/,用户一眼就能分辨页面类型,比你之前把后缀放在slug后面的结构合理很多。
- 方案2:统一调度视图(适合必须保留
/xxx/单级路径的场景)
如果你确实不想在URL里加任何前缀,就需要单独写一个调度视图,先判断slug对应的内容类型再分发处理:
from django.http import Http404 def content_dispatch(request, title): # 先查询是否为新闻 news = News.objects.filter(urltitle=title).first() if news: if request.method == 'POST': form = Commentform(request.POST) if form.is_valid(): form.save() messages.success(request, 'Thank You For Your Comment') else: form = Commentform() return render(request,'news_read.html',{'news':news,'form':form}) # 再查询是否为电影 movie = Movie.objects.filter(urltitle=title).first() if movie: if request.method == 'POST': form = Commentform(request.POST) if form.is_valid(): form.save() messages.success(request, 'Thank You For Your Comment') else: form = Commentform() return render(request,'movie_read.html',{'movie':movie,'form':form}) # 都匹配不到返回404 raise Http404("内容不存在")
路由只需保留一条即可:
path('<slug:title>/',views.content_dispatch,name="content_dispatch"),
注意这个方案需要保证News和Movie表的urltitle字段不会出现重复值,否则会出现内容匹配错误的问题,建议新增数据时做全局slug唯一性校验。
- 额外优化建议:你现有的两个视图代码重复度很高,可以把评论处理、表单初始化的逻辑抽成公共工具函数,后续维护只需要修改一处即可。
内容的提问来源于stack exchange,提问作者Shreyash mishra
相关产品推荐
相关产品推荐

