1

I have 2 forms in one template: UserEditForm and UserRoleForm. As you can see UserRoleForm is a custom Form. How to save form data by post method in Class Based View? get method works fine but I cant save data by post method. Next code raise error which you can see below. It seems to me I try to save forms incorrectly in post method. Where is my mistake?

forms.py:

class UserEditForm(UserChangeForm):
    class Meta:
        model = User
        exclude = ('groups', 'is_superuser', 'is_staff', 'user_permissions',)

class UserRoleForm(forms.Form):
    CHOICES = ((0, _('Admin')), (1, _('Moderator')), (2, _('Simple User')))
    user_role = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)

    def __init__(self, *args, **kwargs):
        super(UserRoleForm, self).__init__(*args, **kwargs)
        self.fields['user_role'].widget.attrs = {
            'id': 'user_role',
        }

view.py:

class UserEditView(UpdateView):
    template_name = 'users/edit_user.html'
    form_class = UserEditForm
    second_form_class = UserRoleForm
    model = User

def post(self, request, *args, **kwargs):
    form = self.form_class(self.request.POST)
    second_form = self.second_form_class(self.request.POST)
    if form.is_valid() and second_form.is_valid():
        new_user = second_form.save(commit=False)
        user_role = second_form.cleaned_data['user_role']
        if user_role==0:
            new_user.is_superuser=True
        elif user_role==1:
            new_user.is_staff=True
        elif user_role==2:
            new_user.is_superuser=False
            new_user.is_staff=False
        new_member.save()
        form.save()
        data = dict()
        data['form_is_valid'] = True
        context = {'users': User.objects.order_by('username')}
        data['html_users'] = render_to_string('users/users.html', context)
    else:
        data = dict()
        data['form_is_valid'] = False
        data['form_errors'] = form.errors
    return JsonResponse(data)

ERROR:

Traceback (most recent call last):
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/views/generic/base.py", line 88, in dispatch
    return handler(request, *args, **kwargs)
  File "/Applications/Projects/web/dashboard.kase.kz/users/views.py", line 82, in post
    if form.is_valid() and second_form.is_valid():
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/forms/forms.py", line 183, in is_valid
    return self.is_bound and not self.errors
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/forms/forms.py", line 175, in errors
    self.full_clean()
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/forms/forms.py", line 384, in full_clean
    self._clean_fields()
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/forms/forms.py", line 405, in _clean_fields
    value = getattr(self, 'clean_%s' % name)()
  File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/contrib/auth/forms.py", line 142, in clean_password
    return self.initial["password"]
KeyError: u'password'

EDIT FORM:

def clean_user_role(self):
    user_role = self.cleaned_data.get('user_role')
    user = ???
    if user_role==0:
        user.is_superuser=True
    elif user_role==1:
        user.is_staff=True
    elif user_role==2:
        user.is_superuser=False
        user.is_staff=False
    return user_role

EDIT VIEW:

def form_valid(self, form):
    user = form.save(commit=False)
    user_role = form.cleaned_data['user_role']
    if "0" in user_role:
        user.is_superuser=True
    elif "1" in user_role:
        user.is_staff=True
    elif "2" in user_role:
        user.is_superuser=False
        user.is_staff=False
    user.save()
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193
  • 3
    You're passing _all_ the POST parameters to a `UserRoleForm`, but it only handles one field, `user_role`. It seems like it would be much easier to just add the `user_role` to `UserEditForm`. –  Nov 20 '17 at 05:53
  • Is it legal to add custom field as `user_role` to `UserEditForm` where every field was taken from `User` model? – Nurzhan Nogerbek Nov 20 '17 at 06:02
  • Can you check my post again pls. At the end of the post I added `clean_user_role`. Is it what I need to do? How to take user by id if clean method? – Nurzhan Nogerbek Nov 20 '17 at 06:29
  • Finally I found solution. I wrote `form_valid` method which you can check in the end of my post. But its interesting to me how to make the same thing in `clean_user_role` method as you said in `forms.py` file? Can you show me it pls, I am little bit comfused. – Nurzhan Nogerbek Nov 20 '17 at 07:57

0 Answers0