如何在Post的DetailView中展示评论与回复表单并解决不显示问题
解决方案:将评论与回复表单集成到Post的DetailView中
你的核心问题是没有把评论、回复表单的实例注入到DetailView的上下文里,同时也没在DetailView中处理这两个表单的提交逻辑。下面一步步帮你解决:
1. 改造DetailView,集成表单展示与提交逻辑
我们需要在DetailView里同时处理表单渲染和POST请求,重写get_context_data和post方法:
from django.shortcuts import redirect from django.views.generic import DetailView from .models import Post, Comment, ReComment from .forms import CommentCreateForm, ReCommentCreateForm class PostDetailView(DetailView): model = Post template_name = 'comment.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 把评论表单、回复表单加入上下文,供模板渲染 context['comment_form'] = CommentCreateForm() context['recomment_form'] = ReCommentCreateForm() # 传递当前帖子ID,方便表单提交使用 context['post_pk'] = self.object.pk return context def post(self, request, *args, **kwargs): self.object = self.get_object() # 通过提交按钮的name属性区分是评论还是回复请求 if 'comment_submit' in request.POST: # 处理评论提交 form = CommentCreateForm(request.POST) if form.is_valid(): comment = form.save(commit=False) comment.target = self.object comment.save() elif 'recomment_submit' in request.POST: # 处理回复提交,获取对应的评论ID form = ReCommentCreateForm(request.POST) if form.is_valid(): comment_pk = request.POST.get('comment_pk') target_comment = Comment.objects.get(pk=comment_pk) recomment = form.save(commit=False) recomment.target = target_comment recomment.save() # 提交完成后重定向回当前详情页 return redirect('comment', pk=self.object.pk)
2. 简化URL配置
现在不需要单独给CommentCreateView和ReCommentCreateView配置URL了,只保留指向改造后PostDetailView的路由:
urlpatterns = [ path('comment/<int:pk>/', views.PostDetailView.as_view(), name='comment'), ]
3. 修改模板,渲染两个表单
调整comment.html,分别渲染评论表单(页面底部)和每个评论对应的回复表单:
{% load static %} <html lang="en"> <head> <meta charset="UTF-8"> <title>COMMENT</title> </head> <body> <div> <h2>{{ object.text }}</h2> </div> <div id="comment-area"> {% for comment in object.comment.all %} <div class="media m-3"> <div class="media-body"> <h5 class="mt-0"> <span class="badge badge-primary badge-pill">{% by_the_time comment.created_at %}</span> {{ comment.name }} <span class="lead text-muted">{{ comment.created_at }}</span> </h5> {{ comment.text | linebreaksbr }} <!-- 每个评论下方的回复表单 --> <form action="" method="POST" enctype='multipart/form-data' class="mt-2"> {% for field in recomment_form %} {% if field.name != 'target' %} <!-- 隐藏自动关联的target字段 --> <div class="form-group"> {{ field.errors }} <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} </div> {% endif %} {% endfor %} <!-- 隐藏字段:传递当前要回复的评论ID --> <input type="hidden" name="comment_pk" value="{{ comment.pk }}"> {% csrf_token %} <input class="btn btn-secondary btn-sm" type="submit" name="recomment_submit" value="Reply"> </form> {% for recomment in comment.recomment.all %} <div class="media m-3"> <div class="media-body"> <h5 class="mt-0"> {{ recomment.name }} <span class="lead text-muted">{{ recomment.created_at }}</span> </h5> {{ recomment.text | linebreaksbr }} </div> </div> {% endfor %} </div> </div> {% endfor %} </div> <!-- 页面底部的评论表单 --> <form action="" method="POST" enctype='multipart/form-data' class="mt-4"> {% for field in comment_form %} <div class="form-group"> {{ field.errors }} <label for="{{ field.id_for_label }}">{{ field.label }}</label> {{ field }} </div> {% endfor %} {% csrf_token %} <input class="btn btn-primary" type="submit" name="comment_submit" value="Comment"> </form> </body> </html>
关键细节提示
- 用提交按钮的
name属性(comment_submit/recomment_submit)区分两种提交请求,让DetailView能正确处理不同表单。 - 回复表单通过隐藏字段
comment_pk传递目标评论ID,后台据此关联回复与评论。 - 模板中表单变量名(
comment_form/recomment_form)必须和DetailView上下文里的变量名完全对应。
现在访问http://localhost:8000/polls/comment/1/就能看到正常显示的评论和回复表单,提交后也会正确保存并刷新页面。
内容的提问来源于stack exchange,提问作者user9179850
相关产品推荐
相关产品推荐

