0

I was able to implement a like counter where it keeps track of all the likes. For some reason though, it randomly doesn't save the counter to the database when I submit the PUT request. I can't figure out when it happens. However, it seems to only happen when I like the post, compared to unliking it. This is how it usually goes:

  1. I press like button - Counter = 1
  2. I press unlike button - Counter = 0
  3. I press like button again - Counter = 0
  4. I press unlike button again - Counter = -1

Thanks for your help!

Here's models.py:

class New_Post(models.Model):
    objects = models.Manager()
    user = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="posts")
    post = models.CharField(max_length=200)
    timestamp = models.DateTimeField(auto_now_add=True, null=True)
    likes = models.ManyToManyField(User, default=None, null=True, blank=True, related_name="all_likes")
    counter = models.IntegerField(null=True)

views.py:

@csrf_exempt
@login_required
def count(request, post_id,):
    posts = New_Post.objects.filter(id=post_id).values()
    print(posts)

    if request.method == "GET":
        return JsonResponse({"posts":list(posts)})

    elif request.method == "PUT":
        posts = New_Post.objects.get(id=post_id)
        data = json.loads(request.body.decode("utf-8"))
        print(data)
        counter = data.get('counter')
        print(counter)
        if counter == None:
            counter = 0
        posts.counter = counter
        print(counter)
        posts.save()
        print(posts.counter)
        return JsonResponse({"message": "Post liked successfully."}, status=201)

It is always printing the right counter, it just sometimes doesn't save it to the database.

edit.js:

document.addEventListener('DOMContentLoaded', function() {

    listen = document.querySelectorAll('.edit');
    likes = document.querySelectorAll('.like');
 
    listen.forEach((form) => {
        form.addEventListener('click', () => {
            console.log(form.name)
            edit(form.name)
        });
    })  
    
    likes.forEach((like) => {
        like.addEventListener('click', () => {
            console.log(like)
            if (like.id == "like") {
                plus_count(like.name)
            }
            else {
                minus_count(like.name)
            }
            likey(like.name) 
        });
    });
});

    function edit(post_id) {

        fetch(`/edit/${post_id}`)
        .then(response => response.json())
        .then(posts => {

            Array.prototype.forEach.call(posts.post, post => {
                console.log(post);
                document.querySelector(`#disable_post-${post.id}`).innerHTML = `<form id="save"> <textarea rows="5" cols="50" id="newpost">${post.post}</textarea> <br> <button class="btn btn-dark" type="submit"> Save </button></form>`;
                document.querySelector(`.button-view-${post.id}`).style.display = 'none';

                document.querySelector('#save').onsubmit = function() {
                    fetch(`/edit/${post_id}`, {
                        method: 'POST',
                        body: JSON.stringify({
                            post: document.querySelector('#newpost').value
                        })
                    });
                }
            });    
        
        });
    }

    function likey(post_id){

        const username = JSON.parse(document.getElementById('username').textContent);
        console.log(username)
        fetch(`/likes/${post_id}`, {
            method: 'PUT',
            body: JSON.stringify({
                likes: username
            })
        });
        window.location.reload(false)
        
    }

    function plus_count(post_id) {

        let counter = document.querySelector(`.count-${post_id}`).innerHTML;
        console.log(counter)

        fetch(`/count/${post_id}`, {
            method: "PUT",
            body: JSON.stringify ({
                counter: Number(counter) + Number(1)
            })
        })
    }

    function minus_count(post_id) {
        
        let counter = document.querySelector(`.count-${post_id}`).innerHTML;
        console.log(counter)

        fetch(`/count/${post_id}`, {
            method: "PUT",
            body: JSON.stringify ({
                counter: Number(counter) - Number(1)
            })
        })
    }
    

Here's part of the index.html template:

{% for post in page_obj %}    
    <div class="container shadow-lg p-3 mb-5 bg-white rounded" id="index-view">
        <div class="background" style="background-color: black;">
            <h4 style="font-family: 'Crimson Text', serif; text-align: center;"><a href="{% url 'profile' post.user %}" id="profile" style="color: white">{{post.user}}</a></h4>
        </div>
        <hr>
        <div id="disable_post-{{post.id}}">
            <p class="text"> {{post.post}} </p>
        </div>
        <br>
        {% if post.counter == None %}
        <p class="count-{{post.id}}"> 0 </p>
        {% else %}
        <p class="count-{{post.id}}"> {{post.counter}} </p>
        {% endif %}

Also this error appeared, no idea if it has anything to do with it:

----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 57410)
Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/socketserver.py", line 720, in __init__
    self.handle()
  File "/Users/Simone/Library/Python/3.8/lib/python/site-packages/django/core/servers/basehttp.py", line 174, in handle
    self.handle_one_request()
  File "/Users/Simone/Library/Python/3.8/lib/python/site-packages/django/core/servers/basehttp.py", line 182, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/socket.py", line 669, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [Errno 54] Connection reset by peer
0

I think you should re-think the whole concept of counting likes. I am really just a newbie but I think it's really, really bad idea getting number from document.querySelector('.count-${post_id}\').innerHTML;.. anybody can access developer mode in web browser and send any number to your server.. And if one user sees 10 likes leaves the page opened whole day and another user get on the page and sees 20 likes and then the first user click like the server gets 11 and... no no no...

I would implement a button which can user click -> send PUT HTTP request with the logged in user id (if user already liked it, disable button in Django template or by JavaScript OR when liked turn it into dislike button) and id of the post -> in your view, you can check if user and post exists, if user has not liked it yet, add him to the list, otherwise remove him or error.. that's up to you..

I would not define counter on the Post model, but some method like:

class User_post(models.Model):

    # your properties
    likes = [...]

    def likes_count():
        return len(likes)

OR

class User(models.Model):
    # your properties
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    dob
    ...

class User_post(models.Model):
    # your properties
    # Many-to-one realationship
    # - user can have more posts
    # - post can have one user
    user = models.ForeignKey(User, ...)
    ...
    
class Likes(models.Model):
    # your properties   
    post = models.ForeignKey(User_post, ...)
    user = models.ManyToManyField(User)
    ...

I may be wrong about the class Likes implementation, as I said, I am a newbie, hope I helped a bit...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .