代码之家  ›  专栏  ›  技术社区  ›  AlexW

Django Crispy forms-内联表单集“ManagementForm数据”与更新视图错误

  •  4
  • AlexW  · 技术社区  · 6 年前

    晚上好,

    https://github.com/timhughes/django-cbv-inline-formset/blob/master/music/views.py https://django-crispy-forms.readthedocs.io/en/latest/crispy_tag_formsets.html#formsets

    编辑 我认为这个问题与双提交按钮有关。devicemodel窗体有一个按钮,按下该按钮会产生此错误。但是资源助手中也有一个save按钮,当它被提交时,我会得到一个空的模型表单错误。

    我添加了操作每个按钮时发生的情况的屏幕截图

    Error when resource save button pressed

    error when update device button is pressed

    ['ManagementForm data is missing or has been tampered with']
    

    以下是我的更新视图:

    class EditDeviceModel(PermissionRequiredMixin, SuccessMessageMixin, UpdateView):
        model = DeviceModel
        form_class = DeviceModelForm
    
        template_name = "app_settings/base_formset.html"
        permission_required = 'config.change_devicemodel'
        success_message = 'Device  Type "%(model)s" saved successfully'
    
        def get_success_url(self, **kwargs):         
            return '{}#device_models'.format(reverse("config:config_settings"))
    
        def get_success_message(self, cleaned_data):
            return self.success_message % dict(
                cleaned_data,
                model=self.object.model,
            )     
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['title']='Edit Device Model'
            if self.request.POST:
                context['formset'] = DeviceFormSet(self.request.POST, instance=self.object)
            else:
                context['formset'] = DeviceFormSet(instance=self.object)
            context['helper'] = DeviceFormSetHelper()
            return context
    
        def form_valid(self, form):
            context = self.get_context_data()
            formset = context['formset']
            if formset.is_valid():
                self.object = form.save()
                formset.instance = self.object
                formset.save()
                return redirect(self.success_url)
            else:
                return self.render_to_response(self.get_context_data(form=form)) 
    

    这是我的表格:

    class MonitoredResourceForm(forms.ModelForm):
        class Meta:
            model = MonitoredResource
            fields = ['resource','model']
    
        def __init__(self, *args, **kwargs):
            self.is_add = kwargs.pop("is_add", False)
            super(MonitoredResourceForm, self).__init__(*args, **kwargs)
            self.helper = FormHelper(self)
            self.helper.form_id = 'snmp_resource_form'
            self.helper.form_method = 'POST'
            self.helper.layout = Layout(
                Div(    
                    Div(
                        Field('model'),
                        Field('resource', placeholder="Resource"),
                        css_class='col-lg-3'
                    ),
                css_class='row'
                ),
                Div(
                    Div(
                        HTML("""<input type="submit" name="submit" value="""),
                        HTML('"Add' if self.is_add else '"Update' ),
                        HTML(""" monitored resource" class="btn btn-primary"/>"""),
                        HTML("""<a href="{% url 'config:config_settings' %}#monitored_resources" class="btn btn-primary">Cancel</a>"""),
                        HTML("""{% if object %}
                                <a href="{% url 'config:delete_monitoredresource' object.id %}"
                                class="btn btn-danger">
                                Delete <i class="fa fa-trash-o" aria-hidden="true"></i></a>
                                {% endif %}"""),
                        css_class='col-lg-12'
                        ),
                    css_class='row'
                    ),
            ) 
    
    class DeviceModelForm(forms.ModelForm):
        class Meta:
            model = DeviceModel
            fields = ['model','vendor','device_type','ports','uplink_speed']
    
        def __init__(self, *args, **kwargs):
            self.is_add = kwargs.pop("is_add", False)
            super(DeviceModelForm, self).__init__(*args, **kwargs)
            self.helper = FormHelper(self)
            self.helper.form_id = 'device_type_form'
            self.helper.form_method = 'POST'
            self.helper.layout = Layout(
                Div(    
                    Div(
                        Field('model', placeholder="Model"),
                        Field('vendor',),
                        Field('device_type',),
                        Field('ports', placeholder="Ports"),
                        Field('uplink_speed', placeholder="Uplink Speed"),
                        css_class='col-lg-6'
                    ),
                css_class='row'
                ),
                Div(
                    Div(
                        HTML("""<input type="submit" name="submit" value="""),
                        HTML('"Add' if self.is_add else '"Update' ),
                        HTML(""" Device Model" class="btn btn-primary"/>"""),
                        HTML("""<a href="{% url 'config:config_settings' %}#device_models" class="btn btn-primary">Cancel</a>"""),
                        HTML("""{% if object %}
                                <a href="{% url 'config:delete_device_model' object.id %}"
                                class="btn btn-danger">
                                Delete <i class="fa fa-trash-o" aria-hidden="true"></i></a>
                                {% endif %}"""),
                        css_class='col-lg-12'
                        ),
                    css_class='row'
                    ),
            )
    
    DeviceFormSet = inlineformset_factory(DeviceModel, MonitoredResource, form=MonitoredResourceForm, extra=1)
    
    class DeviceFormSetHelper(FormHelper):
        def __init__(self, *args, **kwargs):
            super(DeviceFormSetHelper, self).__init__(*args, **kwargs)
            self.form_method = 'post'
            self.render_required_fields = True
            self.form_id = 'snmp_resource_form'
            self.form_method = 'POST'
            self.add_input(Submit("submit", "Save"))
            self.layout = Layout(
                Div(    
                    Div(
                        Field('model'),
                        Field('resource', placeholder="Resource"),
                        css_class='col-lg-6'
                    ),
                css_class='row'
                ),
            ) 
    

    在我呈现的模板中:

    {% block content %} 
    {% include "home/form_errors.html" %}
    <div class="col-lg-6">
        {% crispy form %}
    </div>
    <div class="col-lg-6">
        {% crispy formset helper %}
    </div>
    <!-- /.row -->
    {% endblock %}
    

    3 回复  |  直到 6 年前
        1
  •  1
  •   Ashfaque Ali Solangi    6 年前

    我认为你必须在模板中呈现管理表单, explained here why you need that

    表单集使用管理表单来管理表单集中包含的表单集合。如果您不提供此管理数据,将引发异常

    {{ DeviceFormSet.management_form }}
    
        2
  •  0
  •   Rakon_188    6 年前

    你丢失了一个标签{{格式管理表格|酥脆的

        3
  •  0
  •   rchurch4    6 年前

    您的问题是,表单集中的每个表单都有自己的 management_form . 我并没有在crispy中专门处理这个问题,但是在一般的表单中,这就是我遇到的问题。您必须手动拼出表单集的每一部分,无论是通过迭代还是硬编码,并确保每一部分都有自己的代码 .

        4
  •  0
  •   Austin not from Boston    4 年前

    我也遇到了同样的问题,并在报告中找到了答案 documentation

    {{ formset.management_form|crispy }}
    {% for form in formset %}
        {% crispy form %}
    {% endfor %}