8

I am trying to post comment with ajax, but it is not working. When I press button console is not printing any error (like 404 etc.), comment is not being posted. Object returned by error:

{readyState: 4, getResponseHeader: ƒ, getAllResponseHeaders: ƒ, setRequestHeader: ƒ, overrideMimeType: ƒ, …} abort: ƒ (e) always: ƒ () catch: ƒ (e) done: ƒ () fail: ƒ () getAllResponseHeaders: ƒ () getResponseHeader: ƒ (e) overrideMimeType: ƒ (e) pipe: ƒ () progress: ƒ () promise: ƒ (e) readyState: 4 responseText: "↵" setRequestHeader: ƒ (e,t) state: ƒ () status: 200 statusCode: ƒ (e) statusText: "OK" then: ƒ (t,n,r) proto: Object

In command line I see:

"POST / HTTP/1.1" 200 5572

When I change button to "submit" it is posting and responding with proper JSON like:

{"comment": {"id": 16, "author": 1, "content": "test", "post": 12}}

My code is below, any help is appreciated:

views.py

def homepage(request):
    profiles = Follow.objects.filter(follow_by=request.user.profile).values_list('follow_to', flat=True)
    posts = Post.objects.filter(author_id__in=profiles).order_by('-date_of_create')
    if request.method == 'POST':
        form = CommentForm(request.POST)
        if form.is_valid():
            pk = request.POST.get('pk')
            post = Post.objects.get(pk=pk)
            new_comment = Comment.objects.create(
                author = request.user.profile,
                post = post,
                content = form.cleaned_data['content']
            )
            return JsonResponse({'comment': model_to_dict(new_comment)}, status=200)
    form = CommentForm()
    context = {
        'posts': posts,
        'form': form
    }
    return render(request, 'posts/homepage.html', context=context)

template

<div class="comments" id="{{ post.pk }}" style="display: none">
            {% include 'posts/comments.html' %}
            <form action="" method="post" class="commentForm" data-url="{% url 'post_comments' post.pk %}">
                {% csrf_token %}
                <input type="hidden" name="pk" value="{{ post.pk }}">
                {{ form.as_p }}
                <button type="button" class="commentBtn" id="{{ post.pk }}">Comment</button>
            </form>

addComment.js

$(document).ready(function () {
    $('.commentBtn').click(function () {
        let serializedData = $('.commentForm').serialize();
        let btn = $(this);
        let id = btn.attr('id');
        console.log($(".commentForm").data('url'));
        $.ajax({
            url: $(".commentForm").data('url'),
            data: serializedData,
            type: 'post',
            dataType: 'json',
            success: function (data) {
                console.log(data);
                $(`#${id}.comments`).load('/posts/comments/' + data.post);
                $('textarea').val('');
            },
            error: function(textStatus) {
                console.log(textStatus)
            }
        })
    })
})

Edit: I used this question: Ajax request returns 200 OK, but an error event is fired instead of success , deleted dataType: 'json' and added contentType: 'application/json' and now I got 403 error.

bkrop
  • 228
  • 2
  • 10
  • Hi, you miss `.` near `$("commentForm").data('url')..` . – Swati Oct 27 '20 at 04:11
  • Hi, thanks but it does not help. – bkrop Oct 27 '20 at 05:05
  • 2
    Also , do one thing `$('.commentForm').serialize()` print this and see what its giving .As i can see in your code there are mutliple post and every post will have comment section ..so this will be sending data from all form with class `commentForm` .Instead change it like `$(this).closest(".commentForm").serialize()` so this will get data only from form where button has been clicked . – Swati Oct 30 '20 at 04:03
  • 1
    And that was the problem. Thanks a lot. Post it as answer to get extra bounty ;). PS: how to make form not disappear after posting comment? – bkrop Oct 30 '20 at 05:08

1 Answers1

4

As you have use $('.commentForm') to send data of form to backend it will get all forms with class commentForm and send data of all forms that's the reason its not working .Instead you can change this $('.commentForm').serialize() to $(this).closest(".commentForm").serialize().

Also , you are using #${id}.comments inside success function of ajax this will override any content inside #${id}.comments and load new content from url i.e : /posts/comments/.. .So , to avoid this one way would be surround your {% include 'posts/comments.html' %} with some outer div and then change your selector i.e : #${id}.comments > .yourouterdivclassname so new content will be loaded inside that div only thus form will not get removed .

Swati
  • 28,069
  • 4
  • 21
  • 41