我有两个单独的基于类的视图,并希望保留其功能,并让两个CBV指向同一个模板(我试图将两个单独的表单放入一个页面)。
更具体地说,我正在尝试子类化/合并this email view和此password change view,以便我可以让它们指向相同的模板,因为我最终希望两个表单在同一页面上。
我试图通过将它们分类到我自己的视图中来做到这一点:
class MyEmailUpdateView(LoginRequiredMixin, EmailView):
template_name = 'account/account_settings'
success_url = reverse_lazy('settings')
def form_valid(self, form):
return super(SettingsUpdateView, self).form_valid(form)
class MyPasswordUpdateView(LoginRequiredMixin, PasswordChangeView):
template_name = 'account/account_settings'
success_url = reverse_lazy('settings')
def form_valid(self, form):
return super(SettingsUpdateView, self).form_valid(form)
但我现在发现由于错误,一个接一个地说,除非我手动将它传入(success_url,方法等),否则父类中的任何内容实际上都没有转移到我的自定义类。即便如此,我正在继承的原始类中的代码指向其他地方 那么,当组合这两个视图时,我是否需要将所有原始代码复制到我的自定义子类视图中?
这是完成它的正确方法吗?我如何结合这两个视图?我最终想找到一种方法,在我自己的应用程序中将它们的两个表单放在一个页面上。是否有可能使用library's provided templates更简单的方法来实现此目的?
答案 0 :(得分:5)
您可以使用Django Multi Form View在视图中组合多种表单
安装完成后,您可以像下面这样使用它:
class MultiFView(MultiFormView):
form_classes = {
'email_form' : AddEmailForm,
'change_password_form' : ChangePasswordForm
}
record_id = None
template_name = 'web/multi.html'
def forms_valid(self, forms):
email = forms['email_form'].save(commit=False)
email.save()
return super(MultiFView, self).forms_valid(forms)
并在模板中:
{{ forms.email_form.as_p }}
{{ forms.change_password_form.as_p }}
答案 1 :(得分:2)
我认为您可以使用django中的默认类来实现相同的结果。
据我所知,我得到了这样的场景我们有两个django表单,我们需要它在同一个模板中使用,如果这是我们可以使用来自django.contrib.auth.views
的LoginView的场景,它有几个可自定义的选项,就像你可以给出这样的附加表格
class LoginUserView(LoginView):
authentication_form = LoginForm
extra_context = {"register_form": RegistrationForm}
template_name = 'accounts/index.html'
它将使用get context数据方法更新您将能够在模板中获得的表单并相应地使用。如果您不希望使用这样的代码,您仍然可以像这样使用它
class MyEmailUpdateView(LoginRequiredMixin, EmailView):
form_class = EmailForm
template_name = 'account/account_settings'
success_url = reverse_lazy('settings')
def get_context_data(self, **kwargs):
context = super(MyEmailUpdateView, self).get_context_data(**kwargs)
context['password_reset_form'] = ResetPasswordForm
return context
def form_valid(self, form):
return super(MyEmailUpdateView, self).form_valid(form)
然后,您可以根据您的要求处理有效的表格。 如果您需要任何其他要求,希望有所帮助。
答案 2 :(得分:1)
这可以通过为您的视图实现(某种)部分更新方法来解决。
工具强>
首先保护您的敏感数据:
如果代码中的函数(视图或任何常规回调)使用易受包含敏感信息的局部变量,则可以使用sensitive_variables装饰器阻止这些变量的值包含在错误报告中
sensitive_post_parameters()
装饰者:
如果您的某个视图收到一个HttpRequest对象,其POST参数容易包含敏感信息,您可以使用sensitive_post_parameters装饰器阻止这些参数的值包含在错误报告中
在以下后面创建一些代码:
使用ModelForm
创建一个包含您感兴趣的特定字段的表单。不要包含password
字段,因为我们会以不同的方式添加它以满足我们的需求:
myapp/forms.py
:
class PartialUpdateForm(forms.ModelForm):
new_password = forms.CharField(
required=False, widget=forms.widgets.PasswordInput
)
class Meta:
model = MyUser
fields = ('email', 'other_fields',...)
如果您想要保留除exclude
以外的所有其他字段,则可以使用fields
代替password
。 exclude = ('password',)
使用UpdateView
来处理喧嚣,并覆盖它的form_valid
方法来处理部分更新:
myapp/views.py
:
class MyUpdateView(UpdateView):
template_name = 'account/account_settings'
form_class = PartialUpdateForm
success_url = reverse_lazy('settings')
@sensitive_variables('new_password')
@sensitive_post_parameters('new_password')
def form_valid(self, form):
clean = form.cleaned_data
new_password = clean.get('new_password')
if new_password:
form.instance.password = hash_password(new_password)
return super().form_valid(form)
最后,为该视图创建一个网址:
myapp/urls.py
:
...
url(r'^your/pattern/$', MyUpdateView.as_view()),
这样你就可以处理:
使用此解决方案中的代码:Django: Only update fields that have been changed in UpdateView