使用django crispy-forms的表单中的Formset

时间:2015-03-11 20:08:47

标签: django django-forms django-crispy-forms

我试图在前一个问题(django crispy forms: Nesting a formset within a form)中遵循@qris给出的答案,但我在渲染函数中的formset = context[self.formset_name_in_context]处得到了一个KeyError。我不太明白发生了什么。背景来自哪里?我该如何解决这个问题?

在forms.py中,我为AuthorForm创建了一个formset:

AuthorFormSet = formset_factory(AuthorForm)
author_formset = AuthorFormSet()

然后我在其他表单的布局中使用author_formset

self.helper.layout = Layout(
    Div(
        Div('place', 'sample', css_class='col-xs-6'),
        Div('subject_type', 'data_title', css_class='col-xs-6'),
        css_class='row'
    ),
    MultiField(
        "Authors",
        Formset('author_formset'),
    )
)

我在views.py中的最新尝试:

class register(TemplateView):

    form_class = RegistrationForm()
    facility_form = FacilityAndContactForm()

    formsets = {
        'author_formset': AuthorFormSet,
    }

    template_name = "databank/depositors.html"

    def __init__(self, data, files, *args, **kwargs):
        super(register, self).__init__(data, files, *args, **kwargs)
        if 'initial' in kwargs:
            # Formsets treat this parameter completely differently: they
            # expect an array of values instead of just one. So remove it
            # because it will break formsets.
            kwargs.pop('initial')

        for name, formset_class in self.formsets.iteritems():
            # doesn't exist yet, so we can't call its queryset() method
            queryset = formset_class.model._default_manager.filter(
                **{formset_class.fk.name: self.instance})
            extra = 0 if queryset.exists() else 1

            formset = self.construct_formset(formset_class, data, files, *args, prefix=name, extra=extra, **kwargs)
            setattr(self, name, formset)

            helper = getattr(formset.form(), 'helper', None)
            if helper:
                formset.helper = helper

    def construct_formset(self, formset_class, data, files, prefix, extra,
            *args, **kwargs):
        return formset_class(data, files, *args, prefix=prefix, extra=extra,
            **kwargs)

    def get(self, request, *args, **kwargs):
        form_class = self.form_class
        return render(request, self.template_name, {'form_class': form_class,
            'facility_form': self.facility_form, 'author_formset':
             self.formset})

    def post(self, request):
        form_class = RegistrationForm(request.POST, request.FILES)
        facility_form = FacilityAndContactForm(request.POST)

        author_formset=AuthorFormSet(request.POST)
        formsets = {
            'author_formset': author_formset,
        }

        if form_class.is_valid():
            registration = create_registration(form_class)
            dataset_name = registration.dataset.dataset_name
            # more logic here...

        return render(request, 'databank/register.html',
            {'registration_form': form_class, 'facility_form': facility_form,
            'author_formset': author_formset})

1 个答案:

答案 0 :(得分:1)

你必须自己把author_formset放到上下文中:)它无法通过任何其他方式实现。

这就是我自己概括的方法,在我的表格上有一个dict自动构建的子formsets

class MyForm(ModelForm):
    formsets = {
        'author_formset': AuthorFormSet,
    }

    def __init__(self, data, files, *args, **kwargs):
        super(MyView, self).__init__(data, files, *args, **kwargs)
        if 'initial' in kwargs:
            # Formsets treat this parameter completely differently: they
            # expect an array of values instead of just one. So remove it
            # because it will break formsets.
            kwargs.pop('initial')

        for name, formset_class in self.formsets.iteritems():
            # doesn't exist yet, so we can't call its queryset() method
            queryset = formset_class.model._default_manager.filter(
                **{formset_class.fk.name: self.instance})
            extra = 0 if queryset.exists() else 1

            formset = self.construct_formset(formset_class, data, files, *args,
                prefix=name, extra=extra, **kwargs)
            setattr(self, name, formset)

            helper = getattr(formset.form(), 'helper', None)
            if helper:
                formset.helper = helper

    def construct_formset(self, formset_class, data, files, prefix, extra,
            *args, **kwargs):
        return formset_class(data, files, *args, prefix=prefix, extra=extra,
            **kwargs)