如何在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
相关产品推荐
相关产品推荐

