Reputation: 1618
Good day SO!
I'm learning Django (1.8) with class-based-views. Django itself provides an authentication module with the possibility to change the user's password. While using the Django's PasswordChangeForm (which extends Django's SetPasswordForm), I stumble upon the following error:
init() missing 1 required positional argument: 'user'
When I take a look at SetPasswordForm class, I can see it requires an user-object as parameter.
def __init__(self, user, *args, **kwargs):
self.user = user
super(SetPasswordForm, self).__init__(*args, **kwargs)
What did I initially do?
First off, in my view I simply assigned the Django's PasswordChangeForm:
class ChangePassword(LoginRequiredMixin, FormView):
template_name = 'users/reset_password.html'
form_class = PasswordChangeForm
Which led to the error of course, because no user-object has been provided.
So what have I attempted to solve this issue?
Attempt one: Custom form which inherits from PasswordChangeForm and adds the init method.
Since the PasswordChangeForm does not have an init method, I crated a new form class called MyPasswordChangeForm, which inherits from PasswordChangeForm and adds the init:
class MyPasswordChangeForm(PasswordChangeForm):
def __init__(self, request, *args, **kwargs):
super(MyPasswordChangeForm, self).__init__(request.user, *args, **kwargs)
Expected result: MyPasswordChangeForm->inherit from PasswordChangeForm and add init->super init->perform init in SetPasswordForm
Actual result: super is calling the LoginRequiredMixin:
init() missing 1 required positional argument: 'request'
stack-tr l:80 return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
Attempt 'two': minor changes Changing super->MyPasswordChangeFrom to super->PasswordChangeForm
Attempt three: using a mixin, but had same result as above unfortunately.
Attempt four: not done this yet, but would be the final option? But there must be a way to use the django's forms as much as possible.
So my question is... Can somebody give a hint or small explanation on how I can pass the (authenticated) user-object to the Django's SetPasswordForm via Django's PasswordChangeForm, so I can use as much as possible of the currently existing forms.
Thanks in advance!
Upvotes: 0
Views: 1090
Reputation: 948
request
isn't sent by default to the FormView
upon initialization. You have to sneak it in there somehow.
Based on your attempt #1, a good way to do this is overriding the method get_form_kwargs()
in your FormView
, and add request
as a key to the dict it's super
already provides. Then, use the kwargs
in MyPasswordChangeForm
's __init__
to get request
.
Esentially, you'd do something like:
class ChangePassword(LoginRequiredMixin, FormView):
template_name = 'users/reset_password.html'
form_class = PasswordChangeForm
def get_form_kwargs(self, **kwargs):
data = super(ChangePassword, self).get_form_kwargs(**kwargs)
data['request'] = self.request
return data
And then, in your Form's init:
def __init__(self, *args, **kwargs):
request = kwargs.pop("request") # it's best you pop request, so that you don't get any complains for a parent that checks what kwargs it gets
super(MyPasswordChangeForm, self).__init__(request.user, *args, **kwargs)
Upvotes: 5