Django表单提交报错:'NoneType' object is not callable 求助
Django单页面双表单提交报错:'NoneType' object is not callable
我在Django开发用户资料更新页面,用FormView类视图结合get_context_data实现单页展示两个表单(UserUpdateForm和ProfileUpdateForm),用来修改用户名、邮箱、个人简介等信息。表单能正常显示,但点击提交按钮时出现**'NoneType' object is not callable**错误。试过单表单但不符合需求,希望在类视图架构下解决问题,相关代码及错误详情如下:
模板代码
{% extends 'main.html' %} {% load crispy_forms_tags %} {% block title %} Register {% endblock %} {% block body_content %} <h1>Update your profile</h1> <form method="POST" action="" enctype="multipart/form-data"> {% csrf_token %} <fieldset class="form-group"> {{ u_form|crispy }} {{ p_form|crispy }} </fieldset> <div class="form-group"> <button class="btn" type="submit">Update</button> </div> </form> {% endblock %}
视图代码
from django.contrib.auth.models import User from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import FormView from django.urls import reverse from users.forms.forms import UserUpdateForm, ProfileUpdateForm from users.models.users import Profile from django.contrib import messages class UpdateUserView(LoginRequiredMixin, FormView): template_name = 'base/profile.html' model = User, Profile redirect_authenticated_user = True form_classes = {'u_form': UserUpdateForm, 'p_form': ProfileUpdateForm} def form_valid(self, form): if self.request.method == 'POST': u_form = UserUpdateForm(self.request.user, self.request.POST, self.request.FILES, instance=self.request.user) p_form = ProfileUpdateForm(self.request.user.profile, self.request.POST, self.request.FILES, instance=self.request.user.profile) if u_form is not None and p_form is not None and u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() messages.success(self.request, f'Your account has been updated!') return super().form_valid(form) else: messages.success(self.request, f'Sorry, an error occurred while submitting your form. Please check ' f'the information entered and try again. If the problem persists, ' f'please contact customer service for assistance.') return super().form_invalid(form) def get_success_url(self): return reverse('tasks') def get_context_data(self, **kwargs): u_form = UserUpdateForm(instance=self.request.user) p_form = ProfileUpdateForm(instance=self.request.user.profile) context = { 'u_form': u_form, 'p_form': p_form } return context
表单代码
class UserUpdateForm(forms.ModelForm): email = forms.EmailField() class Meta: model = User fields = ['username', 'email'] def update(self): pass class ProfileUpdateForm(forms.ModelForm): class Meta: model = Profile fields = ['bio', 'image']
错误详情
• django\venv\App\lib\site-packages\django\core\handlers\exception.py, line 55, in inner 55. response = get_response(request) … Local vars • venv\App\lib\site-packages\django\core\handlers\base.py, line 197, in _get_response 197. response = wrapped_callback(request, *callback_args, **callback_kwargs) … Local vars • venv\App\lib\site-packages\django\views\generic\base.py, line 103, in view 96. self = cls(**initkwargs) 97. self.setup(request, *args, **kwargs) 98. if not hasattr(self, "request"): 99. raise AttributeError( 100. "%s instance has no 'request' attribute. Did you override " 101. "setup() and forget to call super()?" % cls.__name__ 102. ) 103. return self.dispatch(request, *args, **kwargs) … 104. 105. view.view_class = cls 106. view.view_initkwargs = initkwargs 107. 108. # __name__ and __qualname__ are intentionally left unchanged as 109. # view_class should be used to robustly determine the name of the view Local vars • venv\App\lib\site-packages\django\contrib\auth\mixins.py, line 73, in dispatch 73. return super().dispatch(request, *args, **kwargs) … Local vars • venv\App\lib\site-packages\django\views\generic\base.py, line 142, in dispatch 142. return handler(request, *args, **kwargs) … Local vars • venv\App\lib\site-packages\django\views\generic\edit.py, line 151, in post 151. form = self.get_form() … Local vars • venv\App\lib\site-packages\django\views\generic\edit.py, line 39, in get_form 39. return form_class(**self.get_form_kwargs())
问题原因及解决方法
核心问题
FormView是为单个表单设计的,你在视图里定义了form_classes(复数)但FormView只认form_class(单数)属性。当POST请求触发get_form()方法时,它找不到合法的form_class,导致form_class为None,调用None(**kwargs)就会抛出'NoneType' object is not callable错误。
另外代码还有几个冗余/错误点:
model = User, Profile写法错误,FormView不需要model属性,且不能同时赋值两个模型form_valid方法里重复判断request.method == 'POST'多余,因为form_valid只有在POST且表单验证通过时才会被调用- 实例化表单时多传了第一个参数
self.request.user,ModelForm不需要这个参数,正确参数是instance和data/files
修正后的视图代码
直接用基础View类实现双表单逻辑,比强行适配FormView更清晰:
from django.contrib.auth.models import User from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import View from django.urls import reverse from users.forms.forms import UserUpdateForm, ProfileUpdateForm from users.models.users import Profile from django.contrib import messages from django.shortcuts import render, redirect class UpdateUserView(LoginRequiredMixin, View): template_name = 'base/profile.html' def get(self, request, *args, **kwargs): # GET请求渲染两个表单 u_form = UserUpdateForm(instance=request.user) p_form = ProfileUpdateForm(instance=request.user.profile) return render(request, self.template_name, {'u_form': u_form, 'p_form': p_form}) def post(self, request, *args, **kwargs): # POST请求处理表单提交 u_form = UserUpdateForm(request.POST, instance=request.user) p_form = ProfileUpdateForm(request.POST, request.FILES, instance=request.user.profile) if u_form.is_valid() and p_form.is_valid(): u_form.save() p_form.save() messages.success(request, '你的账号已更新!') return redirect(reverse('tasks')) # 验证失败返回原页面并提示错误 messages.error(request, '提交表单时出错,请检查输入信息后重试。若问题持续,请联系客服。') return render(request, self.template_name, {'u_form': u_form, 'p_form': p_form})
其他小修正
- 模板里的
class=form-group"少了前引号,改成class="form-group" - 表单里的
update方法无实际作用,可以删除
内容的提问来源于stack exchange,提问作者Wamz
相关产品推荐
相关产品推荐

