通过 django 模板和 JS 的动态喜欢和不喜欢按钮的问题

Posted

技术标签:

【中文标题】通过 django 模板和 JS 的动态喜欢和不喜欢按钮的问题【英文标题】:Problems with dynamic like and dislike buttons via django templates and JS 【发布时间】:2021-11-01 13:18:27 【问题描述】:

我正在尝试为我的 cs50w 项目动态创建和使用喜欢和不喜欢的按钮,这当然应该允许用户喜欢或不喜欢帖子并将喜欢的按钮切换到不喜欢的按钮等等。现在,令人恼火的是,类似和不同的机制本身都可以工作,但按钮却让我感到困惑。

    要么我删除后无法创建相反的按钮 通过 javascript 的原始版本(我尝试使用 appendChildCreateElement,无济于事)。 或者,如果帖子有超过 1 个赞,则会显示更多按钮,其中 2/3 是无效按钮,等等。

如果当前用户喜欢任何帖子(喜欢在他们自己的带有 2 个外键的模型中),我会检查 Django 视图,然后如果有任何帖子,那么我将它们作为上下文发送到必要的模板。 在模板本身内部,我检查一个帖子是否与上下文相对应,如果它是,我生成一个 Unlike 按钮,如果不是,我生成一个 Like 按钮。我已经修补过并在 Google 上搜索过,但情况并没有改善...

代码: 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/点赞函数

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");
            ;
        
    );

类似模型

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 视图

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
        )

【问题讨论】:

【参考方案1】:

我在另一个论坛上得到了这个答案。

在 index.html 中

代码:

% if user.is_authenticated %
     % for like in liked %
         % if like.liked_post == page %
            <span class="is-liked-unlike"><button class="btn btn-secondary" id="unlike">Unlike</button></span>
            <span class="is-liked-like"><button class="btn btn-secondary" style="display:none"
                    id="like">Like</button></span>
         % endif %
     % endfor %
     <span class="is-not-liked-likeBtn"><button class="btn btn-secondary" id="like">Like</button></span>
     <span class="is-not-liked-unlikedBtn"><button class="btn btn-secondary" id="unlike"
                    style="display:none">Unlike</button></span>
% endif %

在network.js中,在divs.forEach中:

代码:

div.querySelectorAll(".is-liked-unlike").forEach((unliked) => 
     unliked.nextElementSibling.nextElementSibling.remove();
     unliked.nextElementSibling.nextElementSibling.remove();
);

【讨论】:

以上是关于通过 django 模板和 JS 的动态喜欢和不喜欢按钮的问题的主要内容,如果未能解决你的问题,请参考以下文章

来自js文件的django模板url

url django模板的动态参数

Django 条件模板继承

08-Django 模板

道具被变异(在 django 模板和带有 CDN 的 Vue.js 中)

带有 css/js 的 Django“包含”模板