发布于 2026-01-06 1 阅读
0

如何向你的 Django 博客添加点赞/取消点赞按钮?DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

如何在 Django 博客中添加“点赞/取消点赞”按钮

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

在本迷你教程中,我们将为 Django 博客添加点赞/取消点赞功能。需要注意的是,我们将使用基于类的视图来实现博客文章详情视图 (DetailView) 的此功能。

第二点说明:遗憾的是,我们无法避免每次点击“点赞/取消点赞”按钮后页面都会刷新。为了避免页面刷新,需要使用 Ajax.js 在博客文章详情页的 HTML 代码中实现“点赞/取消点赞”按钮的全部功能。本教程不会重点介绍这种实现方式。

首先,models.py我们需要在 BlogPost 模型中添加以下字段:

# models.py
from django.db import models
from django.contrib.auth.models import User

class BlogPost(models.Model):
    ...
    likes = models.ManyToManyField(User, related_name='blogpost_like')

    def number_of_likes(self):
        return self.likes.count()
Enter fullscreen mode Exit fullscreen mode

“likes”与我们的用户模型之间存在多对多关系,这意味着用户(对象)可以有多个点赞,博客文章也可以有多个点赞。函数`number_of_likes`将返回当前博客文章对象的点赞数。

每次修改 models.py 文件后,我们需要打开终端并执行数据库迁移:

# CLI/Terminal
>> cd C:\Projects\...\YourDjangoAppMainFolder
>> python manage.py makemigrations
>> python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

现在我们来为“点赞”按钮功能创建一个基于函数的视图。在你的view.py文件中,在 BlogPost DetailView 类之前(或之后),定义一个 BlogPostLike 函数:

# views.py
from django.shortcuts import get_object_or_404
from django.http import HttpResponseRedirect
from django.urls import reverse

def BlogPostLike(request, pk):
    post = get_object_or_404(BlogPost, id=request.POST.get('blogpost_id'))
    if post.likes.filter(id=request.user.id).exists():
        post.likes.remove(request.user)
    else:
        post.likes.add(request.user)

    return HttpResponseRedirect(reverse('blogpost-detail', args=[str(pk)]))
Enter fullscreen mode Exit fullscreen mode

'blogpost_id'将作为我们按钮的标识符blogpost_detail.html。每次登录用户点击“点赞”按钮时,我们会获取该用户的 ID,然后检查该用户是否已经点赞过当前博文(更具体地说:如果用户 x 已经点赞过,则从当前博文中移除该点赞;否则,将用户 x 的点赞添加到当前博文)。之后,我们会将用户重定向到同一篇博文的页面(相当于刷新该页面)。

现在,在我们已经实现 BlogPost DetailView 的同一个view.py文件中,我们需要在 get_context_data 中添加以下内容:

# views.py
class BlogPostDetailView(DetailView):
    model = BlogPost
    # template_name = MainApp/BlogPost_detail.html
    # context_object_name = 'object'

    def get_context_data(self, **kwargs):
        data = super().get_context_data(**kwargs)

        likes_connected = get_object_or_404(BlogPost, id=self.kwargs['pk'])
        liked = False
        if likes_connected.likes.filter(id=self.request.user.id).exists():
            liked = True
        data['number_of_likes'] = likes_connected.number_of_likes()
        data['post_is_liked'] = liked
        return data
Enter fullscreen mode Exit fullscreen mode

在我们的get_context_data函数中,我们将获取当前博客文章的主键,并检查当前登录用户是否点赞了该博客文章。我们将此结果存储在一个局部变量中,以便将其作为上下文传递给基于 HTML 的 blogpost_detail 组件。我们还将获取点赞数(调用之前编写的函数),以便直接在 HTML 模板中显示点赞数。

让我们也把这个新的基于函数的视图添加到我们的urls.py

# urls.py
from django.urls import path
from .views import (
    ...
    BlogPostLike,
    ...
)

urlpatterns = [
    ...
    path('blogpost-like/<int:pk>', views.BlogPostLike, name="blogpost_like"),
    ...
]
Enter fullscreen mode Exit fullscreen mode

最后,让我们blogpost_detail.html用 DjangoTemplateLanguage 编写以下内容:

<!-- LIKES -->
{% if user.is_authenticated %}
  <form action="{% url 'blogpost_like' object.id %}" method="POST">
    {% csrf_token %}

    {% if post_is_liked %}
    <button type="submit" name="blogpost_id" value="{{object.id}}" class="btn btn-info">Unlike</button>
    {% else %}
    <button type="submit" name="blogpost_id" value="{{object.id}}" class="btn btn-info">Like</button>
    {% endif %}
  </form>
{% else %}
  <a class="btn btn-outline-info" href="{% url 'login' %}?next={{request.path}}">Log in to like this article!</a><br>
{% endif %}
<strong class="text-secondary">{{ number_of_likes }} Like{{ number_of_likes|pluralize }}</strong>
Enter fullscreen mode Exit fullscreen mode

我们完成了!

点赞按钮示例

文章来源:https://dev.to/radualexandrub/how-to-add-like-unlike-button-to-your-django-blog-5gkg