Django链接跳转404错误:期望导向views.PostList.as_view()失败
questions路由却触发PostDetail的404错误 我设置了导航栏链接指向{% url 'questions' %},对应路径是http://localhost:8000/questions/,期望它路由到views.PostList.as_view(),但访问时出现404错误:
Page not found (404)
No Post matches the given query.
Request Method: GET
Request URL: http://localhost:8000/questions/
Raised by: blog.views.PostDetail
Using the URLconf defined in classroommatrix.urls, Django tried these URL patterns, in this order:admin/
index/ [name='index']
slug:slug/ [name='post_detail']
The current path, questions/, matched the last one.
超链接代码位于templates/base.html第46行:
<a class="nav-link" href="{% url 'questions' %}">Top Questions</a>
已做的调试检查
1. 检查blog/urls.py的URL模式
当前的URL配置如下:
# blog/urls.py (通过classroommatrix/urls.py调用) from . import views from django.urls import path urlpatterns = [ # 博客应用的URL模式 path('index/', views.PostList.as_view(), name='index'), # 首页 path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), # 文章详情页 path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'), # 文章点赞 path('questions/', views.PostList.as_view(), name='questions'), # 问题页面 ]
2. 检查PostDetail视图类
该类仅处理文章详情逻辑,未涉及questions路径:
# blog/views.py from django.shortcuts import render, get_object_or_404, reverse from django.views import generic, View from django.http import HttpResponseRedirect from .models import Post from .forms import CommentForm class PostList(generic.ListView): # 展示所有文章的列表视图 model = Post queryset = Post.objects.filter(status=1).order_by("-created_on") template_name = "questions.html" paginate_by = 6 class PostDetail(View): # 文章详情视图 def get(self, request, slug, *args, **kwargs): queryset = Post.objects.filter(status=1) post = get_object_or_404(queryset, slug=slug) comments = post.comments.filter(approved=True).order_by("-created_on") liked = False if post.likes.filter(id=self.request.user.id).exists(): liked = True return render( request, "post_detail.html", { "post": post, "comments": comments, "commented": False, "liked": liked, "comment_form": CommentForm() }, ) def post(self, request, slug, *args, **kwargs): queryset = Post.objects.filter(status=1) post = get_object_or_404(queryset, slug=slug) comments = post.comments.filter(approved=True).order_by("-created_on") liked = False if post.likes.filter(id=self.request.user.id).exists(): liked = True comment_form = CommentForm(data=request.POST) if comment_form.is_valid(): comment_form.instance.email = request.user.email comment_form.instance.name = request.user.username comment = comment_form.save(commit=False) comment.post = post comment.save() else: comment_form = CommentForm() return render( request, "post_detail.html", { "post": post, "comments": comments, "commented": True, "comment_form": comment_form, "liked": liked }, )
原因
Django的URL匹配是从上到下按顺序匹配的。你当前的urlpatterns中,动态路径<slug:slug>/排在questions/前面,导致访问/questions/时,Django会把questions当作slug参数传给PostDetail视图,试图查找slug为questions的Post,找不到就抛出404错误。
解决方法
调整URL模式的顺序,把固定路径questions/移到动态路径<slug:slug>/的前面:
urlpatterns = [ # 博客应用的URL模式 path('index/', views.PostList.as_view(), name='index'), # 首页 path('questions/', views.PostList.as_view(), name='questions'), # 问题页面 - 移到动态路径前 path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), # 文章详情页 path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'), # 文章点赞 ]
这样Django会优先匹配固定的questions/路径,正确路由到PostList视图,不会再被动态slug路径拦截。
内容的提问来源于stack exchange,提问作者Laurie Crean

