Получение данных из CKEditor с помощью ajax, чтобы не перезагружать страницу*.
Вот мой код:
Код формы из файла product.html:
...
{% comment %} Review Form Start`` {% endcomment %}
<div class="container">
<section class="review-section col-12 mt-4">
{% comment %} Display All Reviews {% endcomment %}
<h3 class="hide-review-heading">Reviews</h3>
{% for review in reviews %}
<div class="review">
<p><strong>{{ review.user.username }}</strong> - {{ review.rating }} stars</p>
<p>{{ review.review | safe }}</p>
</div>
<hr>
{% empty %}
<p>No reviews yet. Be the first to write a review!</p>
{% endfor %}
<h3 class="hide-review-heading">Write a Review</h3>
<strong class="" id="review-response"></strong>
<form action="{% url 'home:ajax_add_review' p.pid %}" method="POST" class="hide-review-form" id="commentForm">
{% csrf_token %}
<div class="form-group mt-3">
{{ review_form.review }}
</div>
<div class="form-group mt-3">
{{ review_form.rating.label_tag }}<br>
{{ review_form.rating }}
</div>
<br>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</section>
</div>
{% comment %} Review Form End {% endcomment %}
{% endblock body %}
review.js:
console.log("review.js loaded");
$("#commentForm").submit(function(e) {
e.preventDefault();
$.ajax({
data: $(this).serialize(),
method: $(this).attr("method"),
url: $(this).attr("action"),
dataType: "json",
success: function(response) {
console.log("Comment saved to DB")
if (response.bool) {
$("#review-response").html("Review saved successfully");
// Assign a class and remove text-danger class if there
$("#review-response").addClass("text-success");
$("#review-response").removeClass("text-danger");
$(".hide-review-form").hide();
$(".hide-review-heading").hide();
}
else {
$("#review-response").html("Error saving review");
$("#review-response").addClass("text-danger");
$("#review-response").removeClass("text-success");
}
}
});
});
urls.py:
from django.urls import path
from . import views
app_name = "home"
urlpatterns = [
path('', views.index, name='index'),
path('collections/<slug:collection_handle>', views.collections, name="collections"),
path('product/<slug:product_handle>', views.product, name="product"),
path('minimal_product/<slug:product_handle>', views.minimal_product, name="minimal_product"),
# path('products/', views.products, name="products"),
path('search/', views.search, name="search"),
path('products/', views.product_list, name="product-list"),
path('product-quick-view/<int:product_id>/', views.product_quick_view, name='product_quick_view'),
path("ajax-add-review/<pid>", views.ajax_add_review, name="ajax_add_review"),
]
Продукт и функция ajax_add_review из представлений:
def product(request, product_handle):
product = Product.objects.filter(handle=product_handle, product_status="in_review").first()
review_form = ProductReviewForm()
reviews = ProductReview.objects.filter(product=product)
if not product:
raise Http404
context = {
"p": product,
"review_form": review_form,
"reviews": reviews,
}
return render(request, 'home/product.html', context=context)
def ajax_add_review(request, pid):
product = Product.objects.get(pid=pid)
user = request.user
# for key, value in request.POST.items():
# print(f'{key}: {value}')
review_text = request.POST.get('review')
rating = request.POST.get('rating')
print(f"Review is: {review_text}")
if not review_text or not rating:
print("Review text or rating is missing")
return JsonResponse({'bool': False, 'error': 'Review text or rating is missing'})
review = ProductReview.objects.create(
user=user,
product=product,
review=review_text,
rating=rating,
)
context = {
'user': user.username,
'review': review.review,
'rating': review.rating,
}
average_reviews = ProductReview.objects.filter(product=product).aggregate(Avg('rating'))
return JsonResponse(
{
'bool': True,
'context': context,
'average_reviews': average_reviews,
}
)
ProductReviewForm из forms.py:
class ProductReviewForm(forms.ModelForm):
# review = forms.CharField(widget=CKEditor5Widget(config_name='review', attrs={'placeholder': 'Write your review here...'}), required=False)
class Meta:
model = ProductReview
fields = ['review', 'rating']
widgets = {
"review": CKEditor5Widget(
attrs={"class": "django_ckeditor_5", 'placeholder': 'Write your review here...'}, config_name="review"
)
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["review"].required = False
Теперь, когда я нажимаю submit, значение рейтинга извлекается, но значение отзыва, я проверил в inspect и вместо {{ review_form.review }}, там было с name="review" и display as none и для ckeditor, где вы отзыв отображается. И я считаю, что отзыв извлекается из .
Это происходило из одного из двух вариантов, что не совсем то, что мне нужно:
- Если я нажимаю кнопку Submit, то появляется "Error saving review" из-за строки в ajax_add_review, которая говорит if not review_text or not rating и во время этого текст в поле отзыва автоматически добавляется в отзыв, поэтому если я нажимаю Submit снова, то все работает.
- Если я удалю e. preventDefault();, а затем добавляю отзыв и нажимаю Submit, он перенаправляет меня на страницу, где отображается JSON, успешно сгенерированный из ajax_add_review, и данные успешно добавляются в базу данных вместе с отзывом.
Что я хочу: чтобы страница не перезагружалась, отзыв и рейтинг добавлялись в базу данных корректно, без необходимости дважды нажимать кнопку Submit.
Помощь будет очень признательна