You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动将评论关联至对应帖子?Django开发问题求助

问题

我有一个创建评论的表单,该表单已能确定评论所属的用户,但无法将评论关联至其对应的帖子。执行时出现错误:/addcom路径下发生ValueError:无法赋值"1":"Comments.connect_post"必须是"Post"的实例。

相关代码如下:

models.py

class Post(models.Model):
    title = models.CharField(max_length=150)
    text = models.CharField(max_length=8000)
    data = models.DateTimeField(auto_now_add=True)
    image = models.ImageField(upload_to='media/', null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    connect_category = models.ManyToManyField('Category')

    def __str__(self):
        return self.title

    def save(self):
        super().save()
        if self.image:
            img = Image.open(self.image.path)

            if img.height > 300 or img.width > 300:
                new_img = (500, 600)
                img.thumbnail(new_img)
                img.save(self.image.path)

    def get_absolute_url(self):
        return reverse('post', args=[str(self.id)])


class Category(models.Model):
    title = models.CharField(max_length=30)



class Comments(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    text = models.CharField(max_length=800)
    approved = 'Approved'
    refused = 'Refused'
    choice = (
        (approved, 'Одобрено'),
        (refused, 'Отказано')
    )
    status = models.CharField(max_length=8, choices=choice, default='Ожидание')
    connect_post = models.ForeignKey('Post', on_delete=models.CASCADE, null=True)

    def get_absolute_url(self):
        return reverse('post', args=[str(self.id)])

views.py

class PostDetail(DetailView):
    model = Post
    template_name = 'post.html'
    context_object_name = 'post'
    form_class = CommentForm
    success_url = ''

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['comment_form'] = CommentForm(initial={'connect_post': self.object.id})
        return context


class CommentCreateView(CreateView):
    form_class = CommentForm
    success_url = '/'
    model = Comments

    def form_valid(self, form):
        form.instance.author = self.request.user
        post_id = form.cleaned_data['connect_post']
        form.instance.connect_post = post_id
        return super().form_valid(form)

forms.py

class CommentForm(forms.ModelForm):
    connect_post = forms.IntegerField(widget=forms.HiddenInput)
    class Meta:
        model = Comments
        fields = {
            'text',
        }
        exclude = ['author', 'connect_post']

urls.py

urlpatterns = [
    path('', PostList.as_view(), name='news'),
    path('post/<int:pk>', PostDetail.as_view(), name='post'),
    path('create/', PostCreate.as_view(), name='post_create'),
    path('<int:pk>/edit/', PostEdit.as_view(), name='post_edit'),
    path('profile/', Profile, name='profile'),
    path('addcom', CommentCreateView.as_view(), name='comment_create'),
    path('usercomments/', user_comments, name="usercomments"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

解决方案

错误核心是:connect_post是外键字段,必须赋值Post模型实例,而不是单纯的ID数字。下面提供两种可行的修改方案:

方案一:保留隐藏字段,转换ID为实例

直接修改CommentCreateView的form_valid方法,将获取到的post_id转换为Post实例:

from django.shortcuts import get_object_or_404

class CommentCreateView(CreateView):
    form_class = CommentForm
    success_url = '/'
    model = Comments

    def form_valid(self, form):
        form.instance.author = self.request.user
        # 获取Post实例,用get_object_or_404避免ID不存在的错误
        post_id = form.cleaned_data['connect_post']
        form.instance.connect_post = get_object_or_404(Post, id=post_id)
        return super().form_valid(form)

方案二:绑定URL与帖子ID(更安全规范)

这种方式不需要在表单中传递隐藏字段,直接从URL参数获取帖子ID,更安全且逻辑清晰:

1. 修改urls.py

将评论创建的URL与帖子ID绑定:

urlpatterns = [
    # ... 其他路径不变
    path('post/<int:pk>/addcom/', CommentCreateView.as_view(), name='comment_create'),
    # ...
]

2. 修改CommentCreateView

从URL的pk参数获取帖子ID,直接关联实例:

from django.shortcuts import get_object_or_404

class CommentCreateView(CreateView):
    form_class = CommentForm
    success_url = '/'
    model = Comments

    def form_valid(self, form):
        form.instance.author = self.request.user
        # 从URL参数获取帖子ID并关联实例
        form.instance.connect_post = get_object_or_404(Post, id=self.kwargs['pk'])
        return super().form_valid(form)

3. 简化forms.py

删除多余的connect_post字段定义:

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comments
        fields = ['text']
        exclude = ['author', 'connect_post']

4. 修改PostDetail的表单初始化

不需要再传递initial参数:

class PostDetail(DetailView):
    # ... 其他属性不变
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['comment_form'] = CommentForm()
        return context

5. 调整模板中的表单提交路径

确保表单提交到绑定帖子ID的URL:

<form action="{% url 'comment_create' post.id %}" method="post">
    {% csrf_token %}
    {{ comment_form.as_p }}
    <button type="submit">提交评论</button>
</form>

内容的提问来源于stack exchange,提问作者MeRKaLyuT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:10:56