Django Crispy формы - ошибка «данных ManagementForm» встроенных наборов форм с представлением обновления - PullRequest
0 голосов
/ 19 ноября 2018

Добрый вечер,

У меня проблемы с хрустящими формами inlineformset. Я следовал инструкциям согласно:

https://github.com/timhughes/django-cbv-inline-formset/blob/master/music/views.py https://django -crispy-forms.readthedocs.io / ен / последний / crispy_tag_formsets.html # FormSets

EDIT Я думаю, что проблема связана с двойными кнопками отправки. форма устройства имеет кнопку, которая при нажатии выдает эту ошибку. но есть также кнопка сохранения как часть помощника ресурса, когда он передается, я получаю ошибку пустой формы модели.

Я добавил скриншоты того, что происходит, когда вы нажимаете каждую кнопку

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 ]

0 голосов
/ 29 ноября 2018

Я думаю, что вы должны отобразить форму управления в своем шаблоне, объяснил здесь, почему вам нужно, чтобы

Форма управления использовалась набором форм для управления набором форм, содержащихся в наборе форм.,Если вы не предоставите эти данные управления, будет сгенерировано исключение

, добавьте его в представление html

{{ DeviceFormSet.management_form }}
0 голосов
/ 06 декабря 2018

Ваша проблема в том, что каждая форма в наборе форм имеет свой собственный management_form. Я не имел дело с этим конкретно в хрустящей, но в общих формах, это была моя проблема. Вы должны вручную прописать каждую часть набора форм, путем итерации или жесткого кодирования, и убедиться, что у каждого есть свой management_form.

0 голосов
/ 24 ноября 2018

Вам не хватает тега, а также {{format.management_form | crispy}} я думаю,

...