You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django影评网站实现评论增删改及用户评论置顶?

问题描述
  • 开发影评网站,要求每个用户对单部电影仅能发布一条评论,支持对该评论进行更新或删除操作,目前仅实现了评论新增(POST)功能,需修改视图、HTML页面或模型以满足需求。
  • 希望将用户自身发布的评论置于评论列表顶部,参考烂番茄网站的展示逻辑。

现有代码

Models.py

class Comment_movie(models.Model):
    comment     = models.TextField(max_length=1000)
    stars       = models.FloatField(
                     blank=False,
                     null=False,
                     default=0, 
                     validators=[MinValueValidator(0.0),
                     MaxValueValidator(10.0)]
                  )

    user        = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
    movie       = models.ForeignKey(Movie, on_delete=models.CASCADE)
    created_at  = models.DateTimeField(default=datetime.now)
    updated_at  = models.DateTimeField(auto_now=True)
    class Meta:
        unique_together = ('user', 'movie')
        indexes = [
        models.Index(fields=['user', 'movie']),
        ]

views.py

def view_movie_detail(request, movie_id):
    if not(Movie.objects.filter(id=movie_id)):
        Movie(id = movie_id).save()
    movie = Movie.objects.get(id=movie_id)
    if request.method == "POST":
        form = Comment_movie_CreateForm(request.POST)
        if form.is_valid():
            Comment_movie(
                comment = form.cleaned_data['comment'], 
                user = request.user,
                stars = form.cleaned_data['stars'],
                movie = movie
            ).save()
        return redirect('view_movie_detail', movie_id=movie_id)
        
    else:
        form = Comment_movie_CreateForm()
        data = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}?api_key={TMDB_API_KEY}&language=en-US")
        recommendations = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}/recommendations?api_key={TMDB_API_KEY}&language=en-US")
        comments = reversed(Comment_movie.objects.filter(movie_id=movie_id))
        average = movie.average_stars()
        context = {
            "data": data.json(),
            "recommendations": recommendations.json(),
            "type": "movie",
            "comments": comments,
            "average" : average,
            "form": form,
        }
        return render(request, "Movie/movie_detail.html", context)

movie.html

<h2>Comments</h2>
    {% if form.errors %}
        <div class = "error_list">
            {% for errors in form.errors.values %}
                {% for error in errors %}
                    {{ error }}<br>
                {% endfor %}
            {% endfor %}
        </div>
    {% endif %}
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form }}
        <button type="submit">Post Comment</button>
    </form>
    {% endif %}
    <hr>

解决方案

1. 模型层(无需修改)

当前Comment_movie模型已通过unique_together = ('user', 'movie')实现“单用户单电影仅一条评论”的约束,同时添加了联合索引提升查询效率,这部分无需改动。

2. 视图层修改

2.1 新增更新/删除逻辑,调整评论排序

修改view_movie_detail函数,区分POST请求的操作类型,同时让当前用户的评论优先展示:

from django.shortcuts import get_object_or_404

def view_movie_detail(request, movie_id):
    # 简化电影实例创建逻辑
    movie, created = Movie.objects.get_or_create(id=movie_id)
    # 检查当前用户是否已有该电影的评论
    user_comment = None
    if request.user.is_authenticated:
        user_comment = Comment_movie.objects.filter(user=request.user, movie=movie).first()

    if request.method == "POST":
        # 处理删除请求
        if 'delete_comment' in request.POST:
            if user_comment:
                user_comment.delete()
            return redirect('view_movie_detail', movie_id=movie_id)
        
        # 处理新增/更新请求:已有评论则更新,无则新增
        form = Comment_movie_CreateForm(request.POST, instance=user_comment)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.user = request.user
            comment.movie = movie
            comment.save()
        return redirect('view_movie_detail', movie_id=movie_id)
        
    else:
        # 根据是否有评论切换表单模式(编辑/新增)
        form = Comment_movie_CreateForm(instance=user_comment)
        # 排序逻辑:当前用户评论放最前,其余按创建时间倒序
        all_comments = Comment_movie.objects.filter(movie=movie)
        if request.user.is_authenticated:
            user_comments = all_comments.filter(user=request.user)
            other_comments = all_comments.exclude(user=request.user).order_by('-created_at')
            comments = list(user_comments) + list(other_comments)
        else:
            comments = all_comments.order_by('-created_at')
        
        data = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}?api_key={TMDB_API_KEY}&language=en-US")
        recommendations = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}/recommendations?api_key={TMDB_API_KEY}&language=en-US")
        average = movie.average_stars()
        
        context = {
            "data": data.json(),
            "recommendations": recommendations.json(),
            "type": "movie",
            "comments": comments,
            "average": average,
            "form": form,
            "user_comment": user_comment,
        }
        return render(request, "Movie/movie_detail.html", context)

关键说明

  • 用get_or_create替代原有的电影实例判断逻辑,代码更简洁。
  • 通过表单instance参数实现“新增/更新”复用:已有评论则填充数据进行更新,无评论则创建新记录。
  • 评论排序拆分当前用户评论和其他评论,确保用户自身评论置顶。

3. HTML页面修改

更新页面,动态切换表单按钮文本,显示删除按钮,并完善评论列表展示:

<h2>Comments</h2>
{% if form.errors %}
    <div class="error_list">
        {% for errors in form.errors.values %}
            {% for error in errors %}
                {{ error }}<br>
            {% endfor %}
        {% endfor %}
    </div>
{% endif %}

<form method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form }}
    {% if user_comment %}
        <button type="submit">Update Comment</button>
        <button type="submit" name="delete_comment" value="1" onclick="return confirm('确定要删除这条评论吗?')">Delete Comment</button>
    {% else %}
        <button type="submit">Post Comment</button>
    {% endif %}
</form>
<hr>

<!-- 评论列表展示 -->
{% for comment in comments %}
    <div class="comment-item {% if comment.user == request.user %}own-comment{% endif %}">
        <p><strong>{{ comment.user.username }}</strong> - {{ comment.created_at|date:"Y-m-d H:i" }} 
            {% if comment.created_at != comment.updated_at %}
                (Updated: {{ comment.updated_at|date:"Y-m-d H:i" }})
            {% endif %}
        </p>
        <p>Rating: {{ comment.stars }}/10</p>
        <p>{{ comment.comment }}</p>
        <hr>
    </div>
{% empty %}
    <p>暂无评论,快来抢沙发!</p>
{% endfor %}

关键说明

  • 根据user_comment变量动态切换按钮文本,已有评论时显示“更新评论”和“删除评论”按钮。
  • 评论列表中标记用户自身评论(可通过own-comment类自定义样式),同时显示创建/更新时间。
  • 添加空评论状态提示,提升用户体验。

内容的提问来源于stack exchange,提问作者user19553515

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:51:20