对 FormView 中的 get_form_kwargs 感到好奇

Posted

技术标签:

【中文标题】对 FormView 中的 get_form_kwargs 感到好奇【英文标题】:Curious about get_form_kwargs in FormView 【发布时间】:2013-09-07 10:32:29 【问题描述】:

我最近在使用 FormView 时遇到问题,发现解决方法是使用 get_form_kwargs。

这是我的代码:

class InternalResetPasswordView(FormView):

template_name = 'reset_password.html'
form_class = forms.InternalPasswordResetForm

# success_message = "Password was reset successfully"

# To get request object
# http://notesondjango.wordpress.com/2012/12/18/modelform-formview-and-the-request-object/
# https://***.com/questions/13383381/show-message-after-password-change
# http://pydanny.com/simple-django-email-form-using-cbv.html
# http://bubuzzz.wordpress.com/2012/05/01/class-based-generic-views-in-django-a-simple-sample/
def get_form_kwargs(self):
    kwargs = super(InternalResetPasswordView, self).get_form_kwargs()
    kwargs['user'] = self.request.user
    return kwargs

def get_success_url(self):
    return reverse('user-detail', kwargs='pk': self.request.user.id)

@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
    return super(InternalResetPasswordView, self).dispatch(*args, **kwargs)   

'''
def get_context_data(self, **kwargs):

    context = super(InternalResetPasswordView, self).get_context_data(**kwargs)
    context['InternalPasswordResetForm'] = context.get('form')

    return context


def get_form_kwargs(self):
    kwargs = super(InternalResetPasswordView, self).get_form_kwargs()
    kwargs['request'] = self.request
    return kwargs

'''
# self.request.user method obtained from
# https://docs.djangoproject.com/en/dev/topics/class-based-views/generic-editing/
def form_valid(self, form):
    current_password = form.cleaned_data['old_password']
    new_password =  form.cleaned_data['new_password1']
    confirm_new_password = form.cleaned_data['new_password2']
    user = self.request.user
    if user.check_password(current_password) and new_password == confirm_new_password:
        user.set_password(new_password)
        user.save()
        # form.valid() redirects to get_success_url
    return super(InternalResetPasswordView, self).form_valid(form)

看了this post之后,我还是不明白为什么必须使用get_form_kwargs,为什么在这种情况下使用self.request而不是self.request.user会得到__init__() got an unexpected keyword argument 'request'

谁能给我解释一下?

感谢大家的帮助:)

【问题讨论】:

【参考方案1】:

get_form_kwargs 方法将返回一个字典,其中包含将传递给表单的__init__ 的 kwarg。现在,如果你有一个表单,它需要一个名为 user 的 kwarg 并传递一个名为 request 的 kwarg,它会抱怨你看到的错误。如果你想传递request 而不是user(这是我通常做的,因为请求包含用户),那么你应该像这样定义你的表单类:

类 RequestForm(forms.Form): def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super(RequestForm, self).__init__(*args, **kwargs)

【讨论】:

你能告诉我我的表单如何期望我的代码中的request,因为我可以将其定义为:def get_form_kwargs(self): kwargs = super(InternalResetPasswordView, self).get_form_kwargs() kwargs['request'] = self.request return kwargs。抱歉格式化,似乎无法让换行符起作用。 使用def get_form-kwargs(self) 方法,您不是在定义表单,您只是在定义哪些kwargs 会将您的视图传递给表单! django Form 需要特定的 kwargs。如果你试图传递一些意想不到的东西,它会抱怨。这就是为什么在调用 super().__init___ 之前必须调用 kwargs.pop() 来删除要在表单实现中使用的请求。 既然FormView实例化了一个表单,那怎么不把request作为参数呢?菜鸟问题在这里>. 在您的InternalResetPasswordView 中,您传递了一个form_class = forms.InternalPasswordResetForm。因此,您的 FormView 将需要实例化一个 InternalPasswordResetForm 实例并将 get_form_kwargs() 方法的结果传递给 __init___ !因此,在您的 InternalPasswordResetForm 中,您必须先从 kwargs 字典中删除任何额外的参数,然后再将其传递给 super.__init__ !错误不在于您的 FormView 实现,而在于您的 Form

以上是关于对 FormView 中的 get_form_kwargs 感到好奇的主要内容,如果未能解决你的问题,请参考以下文章

重定向到 django FormView 中的下一个 URL

使用jquery post时未调用django formview中的post函数

FormView - 指定在 POST 中发送哪些字段

在 FormView 中找不到控件?

FORMVIEW 和 GET

Django:使用 FormView 时可能有多种形式?