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'),
]