Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将两个视图和两个表单合并到一个模板中?_Python_Django - Fatal编程技术网

Python 如何将两个视图和两个表单合并到一个模板中?

Python 如何将两个视图和两个表单合并到一个模板中?,python,django,Python,Django,我有两个独立的基于类的视图,希望保留它们的功能,并让两个CBV指向同一个模板(我试图将两个单独的表单合并到一个页面中) 更具体地说,我正在尝试子类化/组合,这样我就可以让它们指向同一个模板,因为我最终希望两个表单都在同一个页面上 我试图通过将它们子类化到我自己的视图中来实现这一点: class MyEmailUpdateView(LoginRequiredMixin, EmailView): template_name = 'account/account_settings' s

我有两个独立的基于类的视图,希望保留它们的功能,并让两个CBV指向同一个模板(我试图将两个单独的表单合并到一个页面中)

更具体地说,我正在尝试子类化/组合,这样我就可以让它们指向同一个模板,因为我最终希望两个表单都在同一个页面上

我试图通过将它们子类化到我自己的视图中来实现这一点:

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\u url、方法等)。即使如此,我正在子类化的原始类中的代码也指向其他地方。
因此,当组合这两个视图时,是否需要将所有原始代码复制到自定义子类视图中

这是实现它的正确方法吗?如何将这两种观点结合起来?我最终在寻找一种方法,在我自己的应用程序中,将它们的两个表单都放在一个页面上。是否有一种更简单的方法可以使用

您可以使用组合视图中的许多表单

安装后,您可以使用它,如下所示:

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 }}

这可以通过为视图实现(某种)部分更新方法来解决

工具:

首先保护您的敏感数据:

  • 装饰师:

    如果代码中的函数(视图或任何常规回调)使用易受敏感信息影响的局部变量,则可以使用敏感变量装饰器防止这些变量的值包含在错误报告中

  • 装饰师:

    如果您的一个视图接收到一个HttpRequest对象,该对象的POST参数容易包含敏感信息,则可以使用敏感的POST参数装饰器防止这些参数的值包含在错误报告中

  • 在以下步骤之后创建一些代码:

  • 用于为视图创建具有特定感兴趣字段的表单。不要包括
    密码
    字段,因为我们将以不同的方式添加它以满足我们的需要:

    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',...)
    
    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)
    
    ...
    url(r'^your/pattern/$', MyUpdateView.as_view()),
    
    如果要保留除密码以外的所有其他字段,可以在此处使用
    exclude
    ,而不是
    fields
    :例如
    exclude=('password',)

  • 使用来处理拥挤并覆盖它的
    form\u valid
    方法来处理部分更新:

    myapp/views.py

    class PartialUpdateForm(forms.ModelForm):
        new_password = forms.CharField(
            required=False, widget=forms.widgets.PasswordInput
        )
    
        class Meta:
            model = MyUser
            fields = ('email', 'other_fields',...)
    
    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)
    
    ...
    url(r'^your/pattern/$', MyUpdateView.as_view()),
    
  • 最后,为该视图创建url:

    myapp/url.py

    class PartialUpdateForm(forms.ModelForm):
        new_password = forms.CharField(
            required=False, widget=forms.widgets.PasswordInput
        )
    
        class Meta:
            model = MyUser
            fields = ('email', 'other_fields',...)
    
    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)
    
    ...
    url(r'^your/pattern/$', MyUpdateView.as_view()),
    
  • 通过这种方式,您可以处理:

    • 同时更新电子邮件和密码
    • 只有电子邮件更新
    • 只有密码更新


    使用此解决方案中的代码:

    我认为可以使用django中的默认类来实现相同的结果。 据我所知,我得到了这样一个场景,我们有两个django表单,我们需要在同一个模板中使用它,如果这是一个场景,我们可以使用来自
    django.contrib.auth.views
    的LoginView,它有几个可定制的选项,就像您可以提供这样的附加表单一样

    class LoginUserView(LoginView):
        authentication_form = LoginForm
        extra_context = {"register_form": RegistrationForm}
        template_name = 'accounts/index.html'
    
    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)
    
    它将使用get context data方法来更新表单,您将能够在模板中获取并相应地使用该表单。如果您不希望像这样使用代码,您仍然可以像这样使用它

    class LoginUserView(LoginView):
        authentication_form = LoginForm
        extra_context = {"register_form": RegistrationForm}
        template_name = 'accounts/index.html'
    
    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)
    
    然后你可以按照你的要求以有效的形式处理你的帖子。
    如果您需要任何其他要求,希望这有助于返回。

    当您说“我最终希望两个表单位于同一页面上”时,您的意思是希望一个URL指向具有两个表单的页面吗?@ubadub一个URL指向具有两个表单的页面,是的。我更喜欢一种不依赖另一个第三方图书馆的方法……哈哈……就像荷兰人说的:“农民不知道的东西他不吃。”。。正如西蒙所说;-)西蒙,试试这个图书馆。你为什么要重新发明自行车?似乎与我的问题毫无关系。@Simon说,它允许你有一个单一的视图来处理电子邮件或密码更新(或同时更新两者),然后你可以将其添加到一个url中。但如果你这么想。。。