Django中UpdateView无法保存Topic的first_comment字段值求助
问题:Topic的first_comment无法通过UpdateView修改
我开发了一个「论坛-子论坛-主题-评论」结构的Django论坛应用,主题隶属于对应子论坛,评论隶属于对应主题且仅在主题内展示,视图主要基于类视图实现。创建新Topic时,除subject字段外,还需定义初始评论first_comment(该字段属于Topic模型,功能与Comment模型的content字段类似)。
目前遇到的问题:Comment对应的UpdateView(UpdateComment)可正常编辑保存评论,但Topic的first_comment对应的UpdateView(UpdateFirstComment)无报错,页面正常渲染、返回200状态码,但字段内容始终未修改。
相关代码
models.py(仅展示Topic和Comment模型)
class Topic(models.Model): subject = models.CharField(verbose_name='Заголовок', max_length=255, unique=True) first_comment = models.TextField(verbose_name='Сообщение', max_length=2000, default='') slug = models.SlugField(default='', unique=True, max_length=25, editable=False) subforum = models.ForeignKey('Subforum', verbose_name='Раздел', on_delete=models.CASCADE, related_name='subforum') creator = models.ForeignKey(User, verbose_name='Создатель темы', on_delete=models.SET('deleted'), related_name='creator') created = models.DateTimeField(auto_now_add=True) closed = models.BooleanField(default=False) objects = models.Manager() class Meta: ordering = ['id'] verbose_name = 'Обсуждения' verbose_name_plural = 'Обсуждения' def __str__(self): return self.subject def save(self, *args, **kwargs): self.slug = f'topic-{slugify(self.subject)}' return super(Topic, self).save(*args, **kwargs) def get_absolute_url(self): return reverse('forum:topic', kwargs={'topic_slug': self.slug, 'subforum_slug': self.subforum.slug}) class Comment(models.Model): topic = models.ForeignKey('Topic', verbose_name='Тема', on_delete=models.CASCADE, related_name='comments') author = models.ForeignKey(User, verbose_name='Комментатор', on_delete=models.SET('deleted'), related_name='author') content = models.TextField(verbose_name='Текст', max_length=2000) created = models.DateTimeField(verbose_name='Дата публикации', auto_now_add=True) updated = models.DateTimeField(verbose_name='Дата изменения', auto_now=True) objects = models.Manager() class Meta: ordering = ['created'] verbose_name = 'Комментарии' verbose_name_plural = 'Комментарии' def __str__(self): return f'Post of {self.topic.subject} is posted by {self.author.username}.'
views.py(展示关键视图)
class ShowTopic(DetailView): model = Topic template_name = "forum/topic.html" slug_url_kwarg = 'topic_slug' context_object_name = 'topic' paginate_by = 5 def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) topic = self.get_object() comments_list = Comment.objects.filter(topic=topic).order_by('created') paginator = Paginator(comments_list, self.paginate_by) page_number = self.request.GET.get('page', 1) page_obj = paginator.get_page(page_number) context.update({ 'menu': menu, 'comments': page_obj, 'page_obj': page_obj, 'is_paginated': page_obj.has_other_pages(), 'paginator': paginator, 'comm_num': comments_list.count(), }) return context class AddTopic(LoginRequiredMixin, DataMixin, CreateView): form_class = AddTopicForm template_name = 'forum/addtopic.html' page_title = 'Create a new topic' def get_success_url(self): return reverse('forum:topic', kwargs={ 'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.object.slug}) def form_valid(self, form): subforum = Subforum.objects.get(slug=self.kwargs['subforum_slug']) form.instance.creator = self.request.user form.instance.subforum = subforum return super(AddTopic, self).form_valid(form) class UpdateFirstComment(LoginRequiredMixin, DataMixin, UpdateView): model = Topic form_class = AddTopicForm template_name = 'forum/editcomment.html' page_title = 'Edit comment' def get_success_url(self): return reverse('forum:topic', kwargs={ 'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.kwargs['topic_slug'] }) def get_object(self, queryset=None): return Topic.objects.get(slug=self.kwargs['topic_slug'], subforum__slug=self.kwargs['subforum_slug']) def form_valid(self, form): topic = self.get_object() first_comment = topic.first_comment form.instance.creator = self.request.user form.instance.topic = topic form.instance.first_comment = first_comment return super(UpdateFirstComment, self).form_valid(form) class UpdateComment(LoginRequiredMixin, DataMixin, UpdateView): model = Comment form_class = AddCommentForm context_object_name = 'comment' template_name = 'forum/editcomment.html' page_title = 'Edit comment' def get_success_url(self): return reverse('forum:topic', kwargs={ 'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.kwargs['topic_slug'] })
urls.py
app_name = 'forum' urlpatterns = [ path('', SubForumListView.as_view(), name='forum'), path('<slug:subforum_slug>/', TopicListView.as_view(), name='subforum'), path('<slug:subforum_slug>/add_topic/', AddTopic.as_view(), name="add_topic"), path('<slug:subforum_slug>/topics/<slug:topic_slug>/', ShowTopic.as_view(), name='topic'), path('<slug:subforum_slug>/topics/<slug:topic_slug>/edit_topic/', UpdateFirstComment.as_view(), name='edit_topic'), path('<slug:subforum_slug>/topics/<slug:topic_slug>/add_comment/', AddComment.as_view(), name="add_comment"), path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/edit_comment/', UpdateComment.as_view(), name="edit_comment"), path('<slug:subforum_slug>/topics/<slug:topic_slug>/<int:pk>/delete_comment/', DeleteComment.as_view(), name="delete_comment"), ]
问题原因
UpdateFirstComment的form_valid方法存在核心错误:
- 手动将
form.instance.first_comment赋值为原topic的first_comment,直接覆盖了表单提交的新内容,导致修改无法保存到数据库。 form.instance.topic = topic是多余操作,Topic模型中不存在topic字段,属于无效赋值。- 不必要地设置
form.instance.creator = self.request.user,会错误覆盖主题原创建者,不符合编辑初始评论的逻辑。
解决方案
1. 修复UpdateFirstComment的form_valid方法
移除错误的字段赋值逻辑,直接调用父类方法即可:
class UpdateFirstComment(LoginRequiredMixin, DataMixin, UpdateView): model = Topic form_class = AddTopicForm template_name = 'forum/editcomment.html' page_title = 'Edit comment' def get_success_url(self): return reverse('forum:topic', kwargs={ 'subforum_slug': self.kwargs['subforum_slug'], 'topic_slug': self.kwargs['topic_slug'] }) def get_object(self, queryset=None): return Topic.objects.get(slug=self.kwargs['topic_slug'], subforum__slug=self.kwargs['subforum_slug']) # 可选:添加权限验证,仅允许主题创建者编辑初始评论 def dispatch(self, request, *args, **kwargs): self.object = self.get_object() if self.object.creator != request.user: raise PermissionDenied return super().dispatch(request, *args, **kwargs)
2. 确认表单包含first_comment字段
确保AddTopicForm包含first_comment字段,否则表单无法提交修改内容:
from django import forms from .models import Topic class AddTopicForm(forms.ModelForm): class Meta: model = Topic fields = ['subject', 'first_comment'] # 必须包含first_comment字段
内容的提问来源于stack exchange,提问作者TiimeIrre
相关产品推荐
相关产品推荐

