Reputation: 1
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.
Upvotes: 0
Views: 70
Reputation: 5257
In your reply js code there is a problem - you don't have an action for the form
<form id="newForm" method="POST" class="form-insert py-2">' +
should be somehting like
action_url = "{% url 'index:add_comment' object.id %}"
...
' <form id="newForm" method="POST" class="form-insert py-2" action="' + action_url + '">'
Also your js form requires a user field which you are not currently supplying. Try adding:
'<input type='hidden' name="user" value="{request.user.id}">'
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
fields = ('parent', 'content')
and add it after validation in your view
user_comment.post = post
user_comment.user = request.user
user_comment.save()
That way no one can edit the html before sending to impersonate another user.
Upvotes: 0