Jump to content

Python/Django and JS - problem with dynamically rendering like and dislike buttons

PrimeMinister

I'm trying to dynamically create and use like and unlike buttons for my cs50w project, which should of course allow the user to like or unlike a post and switch a like button to an unlike button and so on. Now, the infuriating thing is, the like and unlike mechanics themselves work, but the buttons are screwing with me.

  1. Either I can't get the opposite button to be created after I deleted the original one via Javascript (I tried to use appendChild and CreateElement, to no avail).
  2. Or if a post has more than 1 like then more buttons show up with 2/3 of them being duds, etc.

enter image description here enter image description here

I check in a Django view if the current user has liked any posts (the likes are in their own model with 2 Foreign Keys), then if there are any posts then I send them as context to the necessary templates. Inside the templates themselves, I check if a post corresponds to the context if it does I generate an Unlike button, if not I generate a Like button. I've tinkered and googled but the situation is not improving at all...

Code: index.html:

{% extends "network/layout.html" %}

{{ user.username|json_script:"username" }}

{% block body %}
    <h3 id='greeting'>Brand new posts! Just for you</h3>
    {% for page in pages %}
        <div class="card border-primary post">
            <h5 class="card-header bg-info user_link">{{page.user.username}}</h5>
            <div class="card-body">
                <div class="card-text border-success" id="content">{{page.content}}</div>
            {% if user.is_authenticated %}
                {% if user.username == page.user.username %}
                <div class="card-text border-success" id='edit-controls'>
                    <textarea id="edit-content"></textarea>
                    <button class="btn btn-primary" id='save-edit'>Save Edit</button>
                </div>
                    <button class="btn btn-primary edit">Edit Post</button>
                {% endif %}
            {% endif %}
            </div>
            <div class="card-footer">
                <p id='page_id' style="display: none;">{{page.id}}</p>
                <div class="card-text" id='created_on'>Posted on: {{page.created_on}}</div>
                <span class="card-text" id='likes'>{{page.likes}} people have liked this</span>
                                {% if user.is_authenticated %}
                    {% for like in liked %}
                        {% if like.liked_post == page %}
                            <span><button class="btn btn-secondary" id="unlike">Unlike</button></span>
                        {% endif %}
                        {% if like.liked_post != page %}
                            <span><button class="btn btn-secondary" id="like">Like</button></span>
                        {% endif %}
                    {% empty %}
                        <span><button class="btn btn-secondary" id="like">Like</button></span>
                    {% endfor %}
                {% endif %}
            </div>
        </div>
    {% endfor %}

    <div class="container p-4">
        <div class="pagination justify-content-center">
            <span class="step-links">
              {% if pages.has_previous %}
                  <a href="?page=1">&laquo; first</a>
                  <a href="?page={{ pages.previous_page_number }}">previous</a>
              {% endif %}

                <span class="current">
                    Page {{ pages.number }} of {{ pages.num_pages }}
                </span>

              {% if pages.has_next %}
                  <a href="?page={{ pages.next_page_number }}">next</a>
                  <a href="?page={{ pages.num_pages }}">last &raquo;</a>
              {% endif %}
            </span>
            </div>
        </div>
{% endblock %}

network.js/liking function

function liking()
{
    const divs = document.querySelectorAll(".card-footer");
    divs.forEach((div) => {
        const like_btn = div.querySelector('#like');
        const unlike_btn = div.querySelector("#unlike");
        const page_id = div.querySelector("#page_id");
        if (like_btn !== null)
        {
            like_btn.onclick = () => {
                const like_str = div.querySelector("#likes").textContent;
                let like_amount = parseInt(like_str.substring(0));
                like_amount++;
                div.querySelector("#likes").textContent = `${like_amount.toString()} people have liked this`;
                like_btn.remove();
                like(page_id.textContent, "like");
            };
        }
        if (unlike_btn !== null)
        {
            unlike_btn.onclick = () => {
                const like_str = div.querySelector("#likes").textContent;
                let like_amount = parseInt(like_str.substring(0));
                if (like_amount > 0)
                {
                    like_amount--;
                    div.querySelector("#likes").textContent = `${like_amount.toString()} people have liked this`;
                }
                else if (like_amount === 0)
                {
                    like_amount = 0;
                    div.querySelector("#likes").textContent = `0 people have liked this`;
                }
                unlike_btn.remove();
                like(page_id.textContent, "unlike");
            };
        }
    });
}

like model

class Like(models.Model):
    user = models.ForeignKey(User, on_delete=CASCADE)
    liked_post = models.ForeignKey(Post, on_delete=CASCADE)

    def __str__(self):
        return f"{self.id} - Post {self.liked_post} liked by {self.user}"

    def is_valid_like(self):
        return self.user != None and self.liked_post != None

django views that I use:

def index(request):
    posts = Post.objects.all().order_by('-id')
    pages = Paginator(posts, 10)
    page_num = request.GET.get('page')
    page_obj = pages.get_page(page_num)
    try:
        user_info = User.objects.get(username=request.user.username)
    except User.DoesNotExist:
        user_info=None
        liked_posts = None
    liked_posts = Like.objects.filter(user=user_info)
    print(liked_posts)    
    return render(request, "network/index.html", {
        "pages": page_obj,
        "liked": liked_posts
    })

def render_profile(request, username):
    if request.method == "GET":
        user_info = None
        try:
            user_info = User.objects.get(username=username)
        except Error:
            return render(request, "network/notfound.html")
        posts = Post.objects.filter(user=user_info).reverse()
        followers = Follow.objects.filter(followee=user_info).count()
        follows = Follow.objects.filter(user=user_info).count()
        is_following = True
        try:
            Follow.objects.get(user=request.user, followee=user_info)
        except Follow.DoesNotExist:
            is_following = False
        liked_posts = Like.objects.filter(user=user_info)
        print(liked_posts)    
        JsonResponse({"found": "profile has been found"}, status=200)
        pages = Paginator(posts, 10)
        page_num = request.GET.get('page')
        page_obj = pages.get_page(page_num)
        return render(request, "network/profile.html", {
            "username": user_info.username,
            "pages": page_obj,
            "followers": followers,
            "follows": follows,
            "following": is_following,
            "liked": liked_posts
        })

 

 

Kind Regards

PrimeMinister

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

3 minutes ago, James Evens said:

Dear prime minster,

this isn't stack overflow so update your post with the code and exact issue.

 

Sincerely yours,

James Evans

I updated it

Link to comment
Share on other sites

Link to post
Share on other sites

{% for like in liked %}
  {% if like.liked_post == page %}
     <span><button class="btn btn-secondary" id="unlike">Unlike</button></span>
  {% endif %}
  {% if like.liked_post != page %}
     <span><button class="btn btn-secondary" id="like">Like</button></span>
  {% endif %}
  {% empty %}
  <span><button class="btn btn-secondary" id="like">Like</button></span>
{% endfor %}

You're creating two buttons for every like in liked, regardless. 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×