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

Django电影评论CRUD实现及排序、URL适配问题咨询

Django电影评论CRUD实现方案

需求回顾

用户发布电影评论后仅能操作自己的评论,无需变更URL即可完成评论的更新与删除;同时解决新评论置顶显示、URL不变更下的删改逻辑问题。


问题1:新评论显示在评论列表顶部

现有代码用reversed()在内存中反转评论列表,效率较低且不够规范。直接通过数据库查询时按创建时间倒序排列即可实现置顶,修改视图中的评论查询逻辑:

原代码:

comments = reversed (Comment_movie.objects.filter (movie_id = movie_id))

修改为:

# 按created_at倒序,最新评论排在最前
comments = Comment_movie.objects.filter(movie_id=movie_id).order_by('-created_at')

这样数据库层面直接返回排序后的结果,性能更优,且无需额外内存反转操作。


问题2:无需变更URL实现评论更新与删除

利用同一view_movie_detail视图,通过POST请求的参数区分操作类型(新增/更新/删除),同时验证操作权限(仅评论所有者可操作)。

步骤1:修改视图逻辑,处理多类型POST请求

from django.shortcuts import get_object_or_404

def view_movie_detail(request, movie_id):
    # 确保Movie实例存在,简化原判断逻辑
    movie, created = Movie.objects.get_or_create(id=movie_id)
    # 获取当前用户的该电影评论(如果存在)
    user_comment = Comment_movie.objects.filter(user=request.user, movie=movie).first()

    if request.method == "POST":
        action = request.POST.get('action')
        
        # 新增评论:仅当用户无该电影评论时执行
        if action == 'create' and not user_comment:
            form = Comment_movie_CreateForm(request.POST)
            if form.is_valid():
                Comment_movie.objects.create(
                    comment=form.cleaned_data['comment'],
                    user=request.user,
                    stars=form.cleaned_data['stars'],
                    movie=movie
                )
        
        # 更新评论:仅当前用户有该评论时执行
        elif action == 'update' and user_comment:
            form = Comment_movie_CreateForm(request.POST, instance=user_comment)
            if form.is_valid():
                form.save()
        
        # 删除评论:仅当前用户有该评论时执行
        elif action == 'delete' and user_comment:
            user_comment.delete()
        
        return redirect('view_movie_detail', movie_id=movie_id)
    
    # GET请求渲染页面
    else:
        # 初始化表单:已有评论则用实例填充(用于更新),否则用空表单
        form = Comment_movie_CreateForm(instance=user_comment) if user_comment else Comment_movie_CreateForm()
        data = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}?api_key={TMDB_API_KEY}&language=ja-US")
        recommendations = requests.get(f"https://api.themoviedb.org/3/movie/{movie_id}/recommendations?api_key={TMDB_API_KEY}&language=en-US")
        comments = Comment_movie.objects.filter(movie_id=movie_id).order_by('-created_at')
        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)

步骤2:修改模板,添加更新/删除按钮(仅当前用户可见)

在评论区域中,对当前用户的评论显示更新和删除选项,表单提交到同一URL:

{% if user.is_authenticated %}
<h2>评论</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 %}
    {% if user_comment %}
        <input type="hidden" name="action" value="update">
        <button type="submit">更新我的评论</button>
    {% else %}
        <input type="hidden" name="action" value="create">
        <button type="submit">发布评论</button>
    {% endif %}
    {{ form }}
</form>

<!-- 删除评论按钮:仅当用户有该电影评论时显示 -->
{% if user_comment %}
<form method="POST" style="margin-top:10px;">
    {% csrf_token %}
    <input type="hidden" name="action" value="delete">
    <button type="submit" style="color:red;">删除我的评论</button>
</form>
{% endif %}
{% else %}
<a class="nav-link" href="{% url 'account_login' %}">登录</a>
{% endif %}

<hr>
<table>
    <tr>
        <th>头像</th>
        <th>用户名</th>
        <th>创建时间</th>
        <th>评论内容</th>
        <th>评分</th>
    </tr>
    {% for c in comments %}
    <tr>
        <td><img class="rounded-circle" src="{{ c.user.avatar.url }}" alt="用户头像" width="100" height="100"></td>
        <td>{{ c.user.nickname }}</td>
        <td>{{ c.created_at }}</td>
        <td>{{ c.comment }}</td>
        <td><h2 class="rate" style="--rating: {{ c.stars }}">{{ c.stars }}</h2></td>
    </tr>
    {% endfor %}
</table>

关键说明:

  • 通过action参数区分新增/更新/删除操作,全程复用同一URL;
  • 权限验证:仅评论所有者(user_comment存在且属于当前用户)可执行更新/删除;
  • 表单复用:更新评论时传入instance=user_comment,自动预填充原有评论内容。

现有代码的其他问题修正

  1. 模型语法错误:Movie类的average_stars方法中else: else:重复,修改为:
def average_stars(self):
    comments = self.get_comments()
    n_comments = comments.count()
    if n_comments:
        return sum([comment.stars for comment in comments]) / n_comments
    else:
        return 0
  1. 视图变量错误:原代码中Recommendation与recommendations变量名大小写不一致、Context字典键值不匹配(如"Comment": Comment应为"comments": comments),已在修改后的视图中修正;
  2. 评论创建冗余代码:原代码中Comment_movie创建时重复写了user = request.user和star = form.cleaned_data['stars'],已删除冗余内容。

内容的提问来源于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 21:45:35