Home > Software engineering >  Saving a comment under an article returns 404 page not found
Saving a comment under an article returns 404 page not found

Time:11-06

I have been trying to add comments to a blog page that I am creating. I have a comment model which has a post id as foreign key, and user as well, because I want to allow only users to comment.

class Comment(models.Model):
    post = models.ForeignKey(
        Article, on_delete=models.CASCADE, related_name='comments')
    name = models.ForeignKey(
        User, blank=True, null=True, on_delete=models.SET_NULL)
    email = models.EmailField()
    body = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(default=False)

    class Meta:
        ordering = ['created_on']

However on save, it returns a 404 error.

Not Found: /articles/this-is-first-article/
[05/Nov/2021 16:51:05] "POST /articles/this-is-first-article/ HTTP/1.1" 404 2912

This is my urls:

app_name = 'articles'
urlpatterns = [
    path('', article_search_view, name='search'),
    path('create/', article_create_view, name='create'),
    path('<slug:slug>/', article_detail_view, name='detail'),
]

And this is my view:

def article_detail_view(request, slug=None):
    article_obj = None
    new_comment = None
    comments = None
    comment_form = None
    if slug is not None:
        try:
            article_obj = Article.objects.get(slug=slug)
            comments = article_obj.comments.filter(active=True)
            if request.method == 'POST':
                comment_form = CommentForm(data=request.POST)
                if comment_form.is_valid():
                    new_comment = comment_form.save(commit=False)
                    new_comment.article = article_obj
                    new_comment.save()
                    return redirect(article_obj.get_absolute_url())
                else:
                    comment_form = CommentForm()
        except Article.DoesNotExist:
            raise Http404
        except Article.MultipleObjectsReturned:
            article_obj = Article.objects.filter(slug=slug).first()
        except:
            raise Http404
    context = {
        "object": article_obj,
        'comments': comments,
        'new_comment': new_comment,
        'comment_form': comment_form
    }
    return render(request, "articles/detail.html", context=context)

I know this is a trivial problem, but if you could help me understand what is going wrong, I would greatly appreciate. And I also would like to make it so that users can comment to comments, but that might be for a different time, because I haven't tried myself yet. But if you have a quick solution, please do let me know.

CodePudding user response:

for now you can first pass the primary_key and the slug just like stackoverflow does with these urls.this will help you to be sure that the .get() method will give you one item.and i use get_object_or_404 to avoid having try and except.

    from django.shortcuts import get_object_or_404
    def article_detail_view(request,slug=None):
        article_obj = None
        new_comment = None
        comments = None
        comment_form = None
        if slug is not None:

            article_obj = get_object_or_404(Article,slug=slug)
            comments = article_obj.comments.filter(active=True)
            if request.method == 'POST':
                comment_form = CommentForm(data=request.POST)
                if comment_form.is_valid():
                    new_comment = comment_form.save(commit=False)
                    new_comment.post = article_obj
                    new_comment.save()
                    return redirect(article_obj.get_absolute_url())
            else:
                comment_form = CommentForm()
        context = {
            'object': article_obj,
           'comments': comments,
           'new_comment': new_comment,
        'comment_form': comment_form
        }
        return render(request, "articles/detail.html", context=context)

change your urls:

app_name = 'articles'
urlpatterns = [
    path('', article_search_view, name='search'),
    path('create/', article_create_view, name='create'),
    path('<slug:slug>/', article_detail_view, name='detail'),
]
  • Related