Please, I need help with my code, I have been unable to figure out my mistake for two days. I have a comment system that work properly but I want user to be able to reply comments. My issue now is that the reply comment is not submitting as I keep having the error:
This page isn’t working right now. If the problem continues, contact the site owner. HTTP ERROR 405
Below is my view.py associated with it
class BlogDetailsView(DetailView):
model = models.BlogPost
template_name = 'home/blog_details.html'
def get_context_data(self, *args, **kwargs):
get_likes = get_object_or_404(models.BlogPost, id=self.kwargs['pk'])
context = super().get_context_data(*args, **kwargs)
post = self.get_object()
context['comments'] = post.comments.filter(status=True)
context['comment_form'] = NewCommentForm()
total_likes = get_likes.total_likes()
liked = False
if get_likes.likes.filter(id=self.request.user.id).exists():
liked = True
context['total_likes'] = total_likes
context['liked'] = liked
return context
def add_comment(request, pk):
post = get_object_or_404(models.BlogPost, pk=pk)
comments = post.comments.filter(status=True)
if request.method == "POST":
comment_form = NewCommentForm(request.POST)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
user_comment.post = post
user_comment.save()
return redirect('index:blog_details', pk=pk)
else:
comment_form = NewCommentForm()
return redirect('index:blog_details', pk=pk)
Below is urls.py
app_name = 'index'
urlpatterns = [
path('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url('images/favicon.ico'))),
path('', views.home, name = 'home'),
path('blog/', BlogHomeView.as_view(), name="blog_list"),
path('blog/<int:pk>/', BlogDetailsView.as_view(), name='blog_details'),
path('add_post/', AddPostView.as_view(), name='add_post'),
path('blog/edit/<int:pk>', EditPostView.as_view(), name='edit_post' ),
path('blog/<int:pk>/delete', DeletePostView.as_view(), name='delete_post' ),
path('like/<int:pk>', views.LikeView, name='like_post'),
path('job/', JobHomeView.as_view(), name="job_list"),
path('job/<int:pk>/', JobDetailsView.as_view(), name='job_details'),
path('add_category/', AddCategoryView.as_view(), name='add_category'),
path('category/<str:category_name>/', views.CategoryView, name='category_list'),
path('view_category/', views.ListCategory, name='view_category'),
path('<int:pk>/add_comment/', views.add_comment, name='add_comment')
]
The form.py code
class NewCommentForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorWidget())
parent = TreeNodeChoiceField(queryset=Comment.objects.all())
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['parent'].required = False
self.fields['parent'].label = ''
self.fields['parent'].widget.attrs.update({'class': 'd-none'})
class Meta:
model = Comment
fields = ('user', 'parent', 'content')
widgets = {
'user': forms.TextInput(attrs={'class': 'form-control', 'value': '', 'id':'user_name', 'type': 'hidden'}),
}
And, the associate template code
<!---View of comment for logged in user--> <br><br>
<div class="post-title">
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} Comment{{ total_comments|pluralize }}
</h2>
<small>Discussion on: {{ object.title }}</small><hr>
{% endwith %}
{% load mptt_tags %}
<div>
{% recursetree comments %}
<small><b>{{ node.user }}</b> - {{ node.date }} ({{ node.date|naturaltime }})</small>
<div class="parent-comment" id="{{ node.id }}">{{ node.content|safe }}</div>
<hr>
<button type="submit" class="button" onclick="myFunction('{{ node.id }}')">Reply</button>
<div>
{% if not node.is_leaf_node %}
<div class="children-comment">{{ children }}</div> <hr>
{% endif %}
</div>
{% endrecursetree %}
</div>
<br><br>
<div>
<h2>Make a new comment</h2>
<form id="myForm" method="post" action="{% url 'index:add_comment' object.id %}">
{% csrf_token %}
{{ form.media }}
{{ comment_form.as_p }}
<button type="submit" class="btn btn-secondary">Add comment</button>
</form>
</div>
<script>
var user = "{{ user.id }}";
document.getElementById("user_name").value = user;
function myFunction(id) {
var existingForm = document.getElementById("newForm");
if (existingForm) {
existingForm.remove();
}
var reply = document.getElementById(id);
reply.insertAdjacentHTML(
"afterend",
' <form id="newForm" method="POST" class="form-insert py-2">' +
'<div><h2>Reply</h2></div>' +
'<select name="parent" class="d-none" id="id_parent">' +
'<option value="' +
id +
'" selected="' +
id +
'"></option>' +
"</select>" +
'<label for="id_content">Content:</label>' +
'<textarea name="content" cols="40" rows="5" class="form-control" required id="id_content"></textarea>' +
'{% csrf_token %}' +
'<button type="submit" class="btn-primary btn-lg btn-block">Submit</button>' +
"</form>"
);
}
$(document).ready(function() {
$('#myForm').trigger('reset');
});
</script>
<style>
.parent-comment {
border: 1px solid rgb(164, 172, 243);
}
.children-comment {
margin-left: 5rem;
border: 1px solid gray;
}
</style>
</div>
<!---End of view of comment for logged in user
I have twerk the views, form, template and urls codes severally but the error persists. I checkedif the add_comment views allows the post method. I played around with the code that I lost my initial code but still have not figured it out.
In your reply js code there is a problem - you don't have an action for the form
should be somehting like
Also your js form requires a user field which you are not currently supplying. Try adding:
somewhere in your form construction.
OR
Strictly speaking, if user is always going to be the request.user, you can remove it from your form definition
and add it after validation in your view
That way no one can edit the html before sending to impersonate another user.