On site exists form where users able to comment products. Comments are connected with products. jQuery is used from Bootstrap base.html (it's worked with another ajax-call). I'm fighting with ajax comment during the week). Trying to do it only for one product to understand how it works. Without ajax system of comments works fine, but I decided to add smooth in comment add without refreshing of the page and I do task with POST and ajax for the first time (before I did two pretty simple examples with get and form reset after successful response to ajax from back-end). Could somebody advice what should be add in template and view ? I suppose problem is connected with my poor knowledge of js.
I am using
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
because this is working with django 4.0, and old function is_ajax()
was removed.
views.py
def ajax_test(request):
product = Product.objects.get(id=4)
comments = product.comment_set.order_by('-created_at')
form = UserCommentForm
context = {'product':product,'comments':comments,'form': form}
return render(request, 'store/ajax_test.html', context)
def ajax_receiver(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if request.method == 'POST' and is_ajax:
product = Product.objects.get(id=4)
form = UserCommentForm(data=request.POST)
user = Comment.objects.get(author=user)
if form.is_valid() and request.user.is_authenticated:
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.product = product
new_comment.save()
comment_info = {
"author": new_comment.author,
"new_comment": new_comment.content,
"created_at": new_comment.created_at,
}
return JsonResponse({"comment_info": comment_info}, status=200)
else:
return JsonResponse({"success": False}, status=400)
template
{% extends "store/base.html" %}
{% load bootstrap4 %}
{% block page_header %}
<h1>тестирую аякс</h1>
{% endblock page_header %}
{% block content %}
<div >
<div >
<div id="sticky-sidebar">
<div >
<form id="UserCommentForm" method='post' >
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" name="comment">Добавить комментарий</button>
{% endbuttons %}
</form>
</div>
</div>
<div id="main">
<h3>Комментарии:</h3>
{% for comment in comments %}
<h6 >
{{ comment.author }}<small> добавлен {{ comment.created_at|date:'M d, Y H:i' }} </small>
</h6>
<div >
<h4>{{ comment }}</h4>
<form action="" method="POST">
{% csrf_token %}
</form>
</div>
{% empty %}
<p>Для данного товара ещё нет комментариев.</p>
{% endfor %}
</div>
</div>
</div>
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#UserCommentForm").submit(function(e) {
// prevent from normal form behaviour
e.preventDefault();
// serialize the form data
var serializedData = $(this).serialize();
$.ajax({
type : 'POST',
url : "{% url 'store:ajax_receiver' %}",
data : serializedData,
success : function(response){
??? what should be there to post ???
},
error : function(response){
console.log(response)
}
});
});
});
</script>
{% endblock javascript %}
{% endblock content %}
Finally I found the decision, it's just to reload block of comments without refreshing, there is the code, the space before ' #main' is important!:
<script type="text/javascript">
$(document).ready(function(){
$("#UserCommentForm").submit(function(e){
// prevent from normal form behaviour
e.preventDefault();
// serialize the form data
var serializedData = $(this).serialize();
$.ajax({
type : 'POST',
url : "{% url 'store:ajax_receiver' %}",
data : serializedData,
success : function(response){
$('#main').load(' #main', function(){
/// can add another function here
});
$("#UserCommentForm")[0].reset();
},
error : function(response){
console.log(response)
}
});
});
});
</script>
CodePudding user response:
In your ajax success write the following code to show new comment:
let comment_info = response["comment_info"];
let author = comment_info["author"];
let comment = comment_info["comment"];
let created_at = comment_info["created_at"];
html = "<h6 class='card-header'> " author "</h6>"
// i have writting only part of html write the full just like you do when you show comments
$("#main").append(html);