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,自动预填充原有评论内容。
现有代码的其他问题修正
- 模型语法错误:
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
- 视图变量错误:原代码中
Recommendation与recommendations变量名大小写不一致、Context字典键值不匹配(如"Comment": Comment应为"comments": comments),已在修改后的视图中修正; - 评论创建冗余代码:原代码中
Comment_movie创建时重复写了user = request.user和star = form.cleaned_data['stars'],已删除冗余内容。
内容的提问来源于stack exchange,提问作者user19553515
相关产品推荐
相关产品推荐

