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

Django提交评论报错:PostDetail.post()收到多个slug参数

Django提交评论触发TypeError问题解决

提交博客评论时出现报错:TypeError: PostDetail.post() got multiple values for argument 'slug',预期流程是评论提交后进入审核,通过后展示。

报错回溯

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/blog/cubs/post/should-be-the-final-test-lmao/

Django Version: 4.1.2
Python Version: 3.10.6
Installed Applications:
['beavers.apps.BeaversConfig',
 'cubs.apps.CubsConfig',
 'scouts.apps.ScoutsConfig',
 'accounts.apps.AccountsConfig',
 'executive.apps.ExecutiveConfig',
 'main_website.apps.MainWebsiteConfig',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.sites',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.sitemaps',
 'django.contrib.staticfiles',
 'django_summernote',
 'crispy_bootstrap5',
 'taggit_helpers',
 'taggit_labels',
 'debug_toolbar',
 'admin_reorder',
 'crispy_forms',
 'storages',
 'taggit']
Installed Middleware:
('whitenoise.middleware.WhiteNoiseMiddleware',
 'whitenoise.middleware.WhiteNoiseMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware',
 'admin_reorder.middleware.ModelAdminReorder')

Traceback (most recent call last):
  File "/home/kiza054/.local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/kiza054/.local/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/kiza054/.local/lib/python3.10/site-packages/django/views/generic/base.py", line 103, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/kiza054/.local/lib/python3.10/site-packages/django/contrib/auth/mixins.py", line 73, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/kiza054/.local/lib/python3.10/site-packages/django/views/generic/base.py", line 142, in dispatch
    return handler(request, *args, **kwargs)

Exception Type: TypeError at /blog/cubs/post/should-be-the-final-test-lmao/
Exception Value: PostDetail.post() got multiple values for argument 'slug'

相关代码

PostDetail视图(views.py)

class PostDetail(LoginRequiredMixin, DetailView):
    model = Post
    form_class = CommentForm
    template_name = "cubs/post_detail.html"

    def get_form(self):
        form = self.form_class(instance=self.object)
        return form

    def post(self, slug, *args, **kwargs): 
        new_comment = None
        pk = self.kwargs.get('pk')
        post = get_object_or_404(Post, pk=pk)
        form = CommentForm(request.POST) 
        if form.is_valid(): 
            # Create new_comment object but don't save to the database yet
            new_comment = form.save(commit=False)
            # Assign the current post to the comment
            new_comment.post = post
            # Save the comment to the database
            new_comment.save()
            messages.warning(request, "Your comment is awaiting moderation, once moderated it will be published")
            return redirect('cubs_blog_post_detail', slug=slug) 
        else: 
            return render(request, self.template_name, {'form': form}) 

    def get_context_data(self, *args, **kwargs):
        slug = self.kwargs.get('slug')
        context = super().get_context_data(**kwargs)
        post = get_object_or_404(Post, slug=slug)
        comments = post.cubs_blog_comments.filter(active=True).order_by('-date_posted')
        articles = Article.objects.filter(status=1).order_by('-date_posted')[:2]
        
        post_likes = get_object_or_404(Post, slug=self.kwargs['slug'])
        total_likes = post_likes.total_likes()

        if post_likes.likes.filter(id=self.request.user.id).exists():
            liked = True
        else:
            liked = False

        context['liked'] = liked
        context['articles'] = articles
        context['comments'] = comments
        context['total_likes'] = total_likes
        context['title'] = 'Post Details'

        context.update({
            'comment_form': self.get_form(),
        })

        return context

Comment模型(models.py)

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='cubs_blog_comments')
    name = models.CharField(max_length=80)
    email = models.EmailField()
    comment = models.TextField()
    date_posted = models.DateTimeField(auto_now_add=True)
    active = models.BooleanField(default=False)

    class Meta:
        ordering = ['date_posted']

    def __str__(self):
        return 'Comment {} by {}'.format(self.comment, self.name)

Post模型(models.py)

class Post(models.Model):

    class Status(models.IntegerChoices):
        Draft = 0
        Published = 1

    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='cubs_blog_posts')
    updated_on = models.DateTimeField(auto_now=True)
    content = models.TextField()
    date_posted = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=Status.choices, default=Status.Draft)
    likes = models.ManyToManyField(User, related_name="cubs_blog_posts_likes")

    class Meta:
        ordering = ['-date_posted']

    def __str__(self):
        return self.title

    def total_likes(self):
        return self.likes.count()
    
    def get_absolute_url(self):
        return reverse("cubs_blog_post_detail", kwargs={"slug": str(self.slug)})

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

错误原因及修复方案

1. Post方法签名错误(核心问题)

Django类视图的post方法必须以request作为self之后的第一个参数,当前签名def post(self, slug, *args, **kwargs):会导致request被错误赋值给slug,同时路由传递的slug又通过kwargs传入,最终引发重复传参错误。

2. 冗余的Post查询

DetailView已经通过slug获取了当前Post对象并存储在self.object中,无需再通过pk或slug重复查询。

3. 未正确使用视图的request属性

代码中直接使用request而非self.request,会导致未定义错误。

修正后的PostDetail视图

class PostDetail(LoginRequiredMixin, DetailView):
    model = Post
    form_class = CommentForm
    template_name = "cubs/post_detail.html"
    # 显式声明用slug作为查询字段,替代默认的pk
    slug_field = 'slug'
    slug_url_kwarg = 'slug'

    def get_form(self):
        # 评论表单无需绑定Post实例,直接创建空表单即可
        return self.form_class()

    def post(self, request, *args, **kwargs): 
        new_comment = None
        # 直接使用DetailView已获取的Post对象
        post = self.get_object()
        form = self.form_class(request.POST) 
        if form.is_valid(): 
            new_comment = form.save(commit=False)
            new_comment.post = post
            # 自动填充当前登录用户的姓名和邮箱,避免重复输入
            new_comment.name = request.user.get_full_name()
            new_comment.email = request.user.email
            new_comment.save()
            messages.warning(request, "你的评论正在等待审核,通过后将展示")
            # 使用Post模型的get_absolute_url跳转,更灵活易维护
            return redirect(post.get_absolute_url())
        else: 
            # 获取上下文并传递错误表单,保留页面原有状态
            context = self.get_context_data()
            context['comment_form'] = form
            return render(request, self.template_name, context) 

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(**kwargs)
        post = self.object
        comments = post.cubs_blog_comments.filter(active=True).order_by('-date_posted')
        articles = Article.objects.filter(status=1).order_by('-date_posted')[:2]
        
        total_likes = post.total_likes()
        liked = post.likes.filter(id=self.request.user.id).exists()

        context['liked'] = liked
        context['articles'] = articles
        context['comments'] = comments
        context['total_likes'] = total_likes
        context['title'] = '文章详情'
        context['comment_form'] = self.get_form()

        return context

额外优化建议

  • 给CommentForm添加验证规则,拦截空评论或无效邮箱
  • 在Comment模型中添加user外键关联登录用户,方便评论管理与溯源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:35:24