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

在Django中使用CreateView时,表单clean方法无法获取request对象的问题

问题:表单clean方法中无法获取request对象,报错'NoneType' object has no attribute 'user'

我尝试在表单的clean方法中获取request对象,但实际并未成功传递,提交表单时出现错误:'NoneType' object has no attribute 'user'。

我的表单代码

class MyModelForm(ModelForm):
    class Meta:
        model = MyModel
        fields=['question',]

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(MyModelForm, self).__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        data = self.cleaned_data['question']
        user = self.request.user
        if user.author.number_of_questions < 1:
             raise ValidationError("You don't have any questions left")
        return data

我的CreateView代码

class MyModelCreate(generic.CreateView):
    model = MyModel
    fields=['question',]
    def form_valid(self, form):
        # Code
        return super(MyModelCreate, self).form_valid(form)

    def get_success_url(self, **kwargs):
        # obj = form.instance or self.object
        return reverse_lazy('articles:thank-you')

    def get_form_kwargs(self):
        kw = super(MyModelCreate, self).get_form_kwargs()
        kw['request'] = self.request # the trick!
        return kw

    def get_context_data(self, **kwargs):
        #Code
        return context

我原本认为CreateView中的get_form_kwargs方法会将self.request传递给表单的request参数,从而在MyModelForm的clean方法中访问,但运行代码时仍出现上述错误,不清楚request对象未传递的原因。


问题原因及解决方案

核心问题

你的MyModelCreate视图中使用了fields参数,这会让Django自动生成一个默认的ModelForm,而不是你自定义的MyModelForm。所以你在get_form_kwargs中传递的request根本没传到你写的表单里,导致self.request始终是None,访问self.request.user就会触发报错。

修复步骤

  1. 指定自定义表单类
    在MyModelCreate中替换fields=['question',]为form_class = MyModelForm,这样Django才会使用你定义的表单:

    class MyModelCreate(generic.CreateView):
        model = MyModel
        form_class = MyModelForm  # 替换原来的fields参数
        # 其他方法保持不变
    
  2. 修正clean方法的返回值
    表单的clean方法应该返回完整的self.cleaned_data,而不是只返回单个字段的值,否则会丢失验证后的其他数据:

    def clean(self):
        data = self.cleaned_data.get('question')
        user = self.request.user
        if user.author.number_of_questions < 1:
             raise ValidationError("你没有剩余的提问次数了")
        return self.cleaned_data  # 返回完整的cleaned_data
    
  3. 增加request存在性判断(可选但推荐)
    为了避免未登录或request未正常传递时的报错,可以在clean方法开头增加判断:

    def clean(self):
        if not self.request or not self.request.user.is_authenticated:
            raise ValidationError("请先登录")
        data = self.cleaned_data.get('question')
        user = self.request.user
        if user.author.number_of_questions < 1:
             raise ValidationError("你没有剩余的提问次数了")
        return self.cleaned_data
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 03:21:36