When I press the submite button of my form, an error is displayed : 'NoneType' object is not callable error.
The form appears correctly, but when posting I get this error
Globally, I'm trying to have two forms in one (by using get_context_data) for an update page where I can modify bio, user names....
Template :
{% 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 type="submit">Update</button>
</div>
</form>
{% endblock %}
View :
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
Forms :
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']
I tried to use only one form but that's not what I want, I'm also trying to work with class base view and I'm trying to avoid to create two pages for editing.
error details :
• 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())
CodePudding user response:
As you are using Generic FormView, you have not defined form_class
(there is no attribute named form_classes
in the FormView). Hence it is getting None. But as you are rendering two forms, it is better to either pass one form to the super function, or define form_class as one of the forms you are using. So solution is either:
return super().form_valid(u_form) # or p_form
Or
class UpdateUserView(...)
form_class = UserUpdateForm