hyperlink leads to 404 error message, No Post matches the given query, Expecting to lead to `views.PostList.as_view()`

16 views Asked by At

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
            },
        )
1

There are 1 answers

0
Laurie Crean On

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.

# blog/urls.py 
# (called through classroommatrix/urls.py)

[...]

urlpatterns = [
    path('index/', views.PostList.as_view(), name='index'),
    path('questions/', views.PostList.as_view(), name='questions'), # questions page moved up from 2 lines below.
    path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), 
    path('like/<slug:slug>', views.PostLike.as_view(), name='post_like'),
]

After reordering the code like this, 404 error message disappears and the PostDetail view displays as expected.