Home > Software design >  'NoneType' object is not callable error when I submite a form Django
'NoneType' object is not callable error when I submite a form Django

Time:12-28

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

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
  • Related