Django基于类视图+内联表单集自动保存登录用户问题求助
我看到你遇到了Django inline formset保存评论时user_id为空的完整性错误,这是因为你没有正确给formset里的每个评论实例关联当前登录用户——formset的save(commit=False)返回的是实例列表,不是单个实例,直接给它赋值user是无效的。下面是修正后的解决方案:
错误根源
CommentsStudyRequestConcept的user字段是必填项(无null=True),但你的代码中没有正确为formset中的每个评论实例设置user属性- 你误将formset的
save(commit=False)返回的实例列表当作单个实例处理,导致没有给每个新增评论赋值用户
修正后的视图代码
创建视图(StudyRequestConceptFormsetCreate)
class StudyRequestConceptFormsetCreate(CreateView): model = StudyRequestConcept template_name = 'createStudyRequestConcept.html' form_class = StudyRequestConceptForm success_url = reverse_lazy('create_StudyRequestConcept') def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) if self.request.POST: data['comment'] = CommentsStudyRequestConceptFormset(self.request.POST, prefix='comments') else: data['comment'] = CommentsStudyRequestConceptFormset(prefix='comments') return data def form_valid(self, form): context = self.get_context_data() comment_formset = context['comment'] with transaction.atomic(): # 先保存主对象,关联当前用户 self.object = form.save(commit=False) self.object.user = self.request.user self.object.save() # 处理评论formset if comment_formset.is_valid(): # 关联主对象到formset comment_formset.instance = self.object # 获取所有待保存的评论实例(列表) comment_instances = comment_formset.save(commit=False) # 遍历每个实例,设置当前用户 for instance in comment_instances: instance.user = self.request.user instance.save() messages.success(self.request, f'{StudyRequestConcept.__name__} Form ID: {self.object.id} was submitted successfully') return super().form_valid(form) else: # 如果formset无效,返回表单页面显示错误 return self.render_to_response(self.get_context_data(form=form))
更新视图(StudyRequestConceptFormsetUpdate)
编辑时需要注意:只给新增的评论设置当前用户,已有评论保持原用户不变,formset的save(commit=False)只会返回新增和修改的实例,我们可以通过判断实例是否有pk来区分(新实例没有pk):
class StudyRequestConceptFormsetUpdate(UpdateView): model = StudyRequestConcept form_class = StudyRequestConceptEditForm template_name = 'updateStudyRequestConcept.html' success_url = reverse_lazy('edit_StudyRequestConcept') def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) if self.request.POST: data['comment'] = CommentsStudyRequestConceptFormset(self.request.POST, prefix='comments', instance=self.object) else: data['comment'] = CommentsStudyRequestConceptFormset(prefix='comments', instance=self.object) return data def form_valid(self, form): context = self.get_context_data() comment_formset = context['comment'] with transaction.atomic(): # 保存主对象 self.object = form.save() if comment_formset.is_valid(): comment_formset.instance = self.object comment_instances = comment_formset.save(commit=False) for instance in comment_instances: # 只有新创建的评论(无pk)才设置当前用户 if not instance.pk: instance.user = self.request.user instance.save() messages.success(self.request, f'{StudyRequestConcept.__name__} Form ID: {self.object.id} was updated successfully') return super().form_valid(form) else: return self.render_to_response(self.get_context_data(form=form))
额外优化建议
- 可以移除
CommentsStudyRequestConceptForm中的空clean方法,它没有做任何实际校验,还会覆盖父类的默认clean逻辑 - 确保只有登录用户才能操作:给视图添加
LoginRequiredMixin,避免匿名用户提交时出现异常
from django.contrib.auth.mixins import LoginRequiredMixin class StudyRequestConceptFormsetCreate(LoginRequiredMixin, CreateView): # ... 原有代码 ... class StudyRequestConceptFormsetUpdate(LoginRequiredMixin, UpdateView): # ... 原有代码 ...
内容的提问来源于stack exchange,提问作者Amey Kelekar
相关产品推荐
相关产品推荐

