Search code examples
javascripthtmldjangofetch

Stop fetch function from reloading console


I am trying to create a like/unlike button. I am sending a form using fetch to my /like url in python. To test the code I decided to simply return a JSONResponse . It is working but it seems that the page is being reloaded and thus the original state is being returned. That is: original state is 'Unlike', click makes it 'Like' for a small amount of time and then 'Unlike' comes back

Here is my html

 {% if request.user not in post.like.all %}
            <a href="" class="card-link liked" data-id="{{post.id}}" data-is_liked="false" id="post-like-{{post.id}}">

                <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-heart" fill="currentColor"
                    xmlns="http://www.w3.org/2000/svg">
                    <path fill-rule="evenodd"
                        d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z" />
                </svg>

            </a>
            {% else %}
            <a href="" class="card-link liked" data-id="{{post.id}}" data-is_liked="true" id="post-like-{{post.id}}">

                <svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-heart-fill" fill="currentColor"
                    xmlns="http://www.w3.org/2000/svg">
                    <path fill-rule="evenodd"
                        d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z" />
                </svg>

            </a>
            {% endif %}

here is my js script

//this is the script for like edit and delete

var like = document.querySelectorAll(".liked")
like.forEach(element => {
    handleLike(element);
});


function handleLike(element) {
    element.addEventListener('click', () => {

        post_id = element.getAttribute('data-id');
        is_liked = element.getAttribute('data-is_liked');
        icon = document.getElementById(`post-like-${post_id}`);
        count = document.getElementById(`post-count-${post_id}`);
        console.log(post_id, is_liked);
        form = new FormData();
        form.append("post_id", post_id);
        form.append("is_liked", is_liked);
        fetch('/like', {
            method: 'POST',
            body: form,

        }).then((res) => res.json())
            .then((res) => {
                if (res.status == 201)
                    if (res.is_liked === 'true') {
                        {


                            icon.innerHTML = `<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi - heart - fill" fill="currentColor"
                                    xmlns = "http://www.w3.org/2000/svg" >
                                    <path fill-rule="evenodd"
                                    d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z" />
                                    </svg > `; icon.setAttribute('data-is_liked', 'true')
                        }
                    }
            });

    });

}

here is my python view

def like(request):
    if request.method == 'POST':
        post_id = request.POST.get('post_id')
        is_liked = request.POST.get('is_liked')
        return JsonResponse({'is_liked': 'true', 'status': 201}, status=201)

I am new to JS so please help.


Solution

  • The page reloads because you are clicking an <a href="" which points back to the same page. That is the default behaviour of the browser. You should add href="javascript:void(0)"

    For persistence, the comment specifies like is a m2m relation to User. The view should look like this:

    post_id = request.POST.get('post_id')
    post = Post.objects.get(id=post_id)
    is_liked = request.POST.get('is_liked')
    if is_liked:
        post.like.add(request.user)
    else:
        post.like.remove(request.user)
    

    I recommend renaming like to likes