无法将 'user' 参数传递给 Django 中的 ChangePasswordForm

can't pass 'user' parameter to ChangePasswordForm in django

美好的一天!

我正在使用基于 class 的视图学习 Django (1.8)。 Django 本身提供了一个可以更改用户密码的身份验证模块。在使用 Django 的 PasswordChangeForm(它扩展了 Django 的 SetPasswordForm)时,我偶然发现了以下错误:

init() missing 1 required positional argument: 'user'

当我查看 SetPasswordForm class 时,我发现它需要一个用户对象作为参数。

def __init__(self, user, *args, **kwargs):
    self.user = user
    super(SetPasswordForm, self).__init__(*args, **kwargs)


我最初做了什么?
首先,在我看来,我只是分配了 Django 的 PasswordChangeForm:

class ChangePassword(LoginRequiredMixin, FormView):
    template_name = 'users/reset_password.html'
    form_class = PasswordChangeForm

这当然会导致错误,因为没有提供用户对象。

那么我尝试过什么来解决这个问题?

尝试一:自定义表单,继承PasswordChangeForm,增加init方法
由于 PasswordChangeForm 没有 init 方法,我创建了一个名为 MyPasswordChangeForm 的新表单 class,它继承自 PasswordChangeForm 并添加了 init:

class MyPasswordChangeForm(PasswordChangeForm):
    def __init__(self, request, *args, **kwargs):
        super(MyPasswordChangeForm, self).__init__(request.user, *args, **kwargs)

预期结果:MyPasswordChangeForm->继承PasswordChangeForm并添加init->super init->SetPasswordForm中执行init
实际结果:super 正在调用 LoginRequiredMixin:

init() missing 1 required positional argument: 'request'
stack-tr l:80 return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

尝试'two': 小改动 将 super->MyPasswordChangeFrom 更改为 super->PasswordChangeForm

尝试三:使用mixin,不幸的是结果和上面一样。

尝试四:还没有做这个,但会是最后的选择吗?但是必须有一种方法可以尽可能多地使用django的表单。

所以我的问题是... 有人可以就如何通过 Django 的 PasswordChangeForm 将(经过身份验证的)用户对象传递给 Django 的 SetPasswordForm 给出提示或小的解释,这样我就可以尽可能多地使用当前存在的表单。

提前致谢!

默认情况下

request 不会在初始化时发送到 FormView。你必须以某种方式把它偷偷放进去。

根据您的尝试 #1,实现此目的的一个好方法是覆盖 FormView 中的方法 get_form_kwargs(),并将 request 添加为字典的键,它是 super 已经提供了。然后,使用 MyPasswordChangeForm__init__ 中的 kwargs 得到 request.

基本上,你会做类似的事情:

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

然后,在您的表单初始化中:

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)