Получение данных из 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, где вы отзыв отображается. И я считаю, что отзыв извлекается из .

Это происходило из одного из двух вариантов, что не совсем то, что мне нужно:

  1. Если я нажимаю кнопку Submit, то появляется "Error saving review" из-за строки в ajax_add_review, которая говорит if not review_text or not rating и во время этого текст в поле отзыва автоматически добавляется в отзыв, поэтому если я нажимаю Submit снова, то все работает.
  2. Если я удалю e. preventDefault();, а затем добавляю отзыв и нажимаю Submit, он перенаправляет меня на страницу, где отображается JSON, успешно сгенерированный из ajax_add_review, и данные успешно добавляются в базу данных вместе с отзывом.

Что я хочу: чтобы страница не перезагружалась, отзыв и рейтинг добавлялись в базу данных корректно, без необходимости дважды нажимать кнопку Submit.

Помощь будет очень признательна

Вернуться на верх