Expecting hyperlink in index.html to lead to views.PostList.as_view()
hyperlink located in templates/base.html line 46:
<a class="nav-link" href="{% url 'questions' %}">Top Questions</a>
Leads to http://localhost:8000/questions/ as expected but with this error message:
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.
debugging steps taken
So far I've reviewed urlpatterns and views.py as indicated by the error message.
1: review urlpatterns
The problem seems to arise in the urlpatterns in blog/urls.py. The error message indicates that views.PostDetail.as_view() is problematic:
# blog/urls.py (called through classroommatrix/urls.py)
from . import views
from django.urls import path
urlpatterns = [ # url patterns for the blog app here.
path('index/', views.PostList.as_view(), name='index'), # home page
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), # post detail page - !!The error message indicates that PostDetail is problematic:
path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'), # post like
path('questions/', views.PostList.as_view(), name='questions'), # questions page
]
2: review PostDetail
Seems a less likely problem area as there is no mention of 'questions/' in `PostDetail class.
# 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): # this class will list all the posts
model = Post
queryset = Post.objects.filter(status=1).order_by("-created_on")
template_name = "questions.html"
paginate_by = 6
class PostDetail(View): # this class will show the details of a post. The error message indicates that PostDetail is problematic:
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 matches URLs in the order they're listed in urlpatterns. If 'slug:slug/' comes before 'questions/', it will capture any URL that should go to 'questions/'. Therefore best pracrtise is to make sure that the more specific paths come before the more general slug pattern.
After reordering the code like this, 404 error message disappears and the PostDetail view displays as expected.