【问题标题】:Formset within a Form Using django crispy-forms使用 django crispy-forms 的表单中的表单集
【发布时间】:2015-05-13 19:36:38
【问题描述】:

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

在 forms.py 中,我为我的 AuthorForm 创建了一个表单集:

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

【问题讨论】:

  • @qris 我在哪里/如何最初声明布局对象以传递给新的 Formset 字段?在您的示例实现中,您首先在哪里/如何定义“教育”?

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


【解决方案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)

【讨论】:

  • 非常感谢您的帮助!! @qris 我以前从未使用过基于类的视图,所以老实说,我仍然很困惑。 (不过,我现在正在阅读它们,试图理解)。有没有办法使用基于函数的视图来做到这一点?或者,如果我发布更多我目前拥有/正在尝试的内容,你能帮我吗?
  • 我添加了我最新的视图尝试,但我收到了关于未将正确参数传递给 init __init__() takes at least 3 arguments (1 given) 的错误
  • 对不起,我的错误,这段代码来自表单,而不是视图。而是将其添加到您的表单中,然后在您的视图中正常构建它。我已经更新了上面的答案。
  • 感谢您的帮助@qris 无法告诉您我多么感激。不幸的是,我在这里不知所措。我会继续努力,但我认为我需要更多帮助,所以我现在正在努力寻找可能愿意分享屏幕并以这种方式帮助我的人(如果你愿意,请告诉我!但我会找到一些方式)。
猜你喜欢
  • 2022-01-04
  • 2015-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
  • 2021-01-08
  • 2018-07-22
  • 2017-02-02
相关资源
最近更新 更多