【问题标题】:Django formset : Save multiple forms from formsetDjango formset:从formset保存多个表单
【发布时间】:2019-04-15 09:34:10
【问题描述】:

为了add dynamically forms to formset,我花了几天时间,我找到了一种方法。但我对forms saving 有一点问题,因为它只是保存第一个表单,而不是表单集中的所有表单。

这是我的表单集:

DocumentFormSets = inlineformset_factory(Publication, Document, form=DocumentForm, extra=1, max_num=4)

这是我的模板:

<fieldset>
    <legend class="title"><span class="name">{% trans 'Document form' %}</span></legend>
    {{ DocumentFormSet.management_form }}
    <div id="form_set">
      {% for form in DocumentFormSet.forms %}
        <div class='formset-document'>
          <table class='no_error'>
            <div class="row">
              <div class="col-xs-3">
                {{ form.title|as_crispy_field }}
              </div>
              <div class="col-xs-3">
                {{ form.language|as_crispy_field }}
              </div>
              <div class="col-xs-3">
                {{ form.format|as_crispy_field }}
              </div>
              <div class="col-xs-3">
                {{ form.upload|as_crispy_field }}
              </div>
            </div>
          </table>
        </div>
      {% endfor %}
    </div>
    <br>
    <input type="button" class="btn btn-default" value="Add More" id="add_more">
    <div id="empty_form" style="display:none">
      <table class='no_error'>
        <div class="row">
          <div class="col-xs-3">
            {{ DocumentFormSet.empty_form.title|as_crispy_field }}
          </div>
          <div class="col-xs-3">
            {{ DocumentFormSet.empty_form.language|as_crispy_field }}
          </div>
          <div class="col-xs-3">
            {{ DocumentFormSet.empty_form.format|as_crispy_field }}
          </div>
          <div class="col-xs-3">
            {{ DocumentFormSet.empty_form.upload|as_crispy_field }}
          </div>
        </div>
      </table>
    </div>
</fieldset>

这是我的 JS 部分:

$('#add_more').click(function () {
  var form_idx = $('#id_form-TOTAL_FORMS').val();
  $('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
  $('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1);
});

这是我的 views.py 文件:

class PublicationCreateView(EdqmCreateView):
    """ Create publication with document form through formset """
    model = Publication
    template_name = 'freepub/publication/publication_form.html'

    def get_context_data(self, **kwargs):
        context = super(PublicationCreateView, self).get_context_data(**kwargs)
        context['DocumentFormSets'] = DocumentFormSets(self.request.POST or None, self.request.FILES or None)
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        formsets = context['DocumentFormSets']
        if form.is_valid() and formsets.is_valid():
            self.object = form.save()
            formsets.instance = self.object
            formsets.save()
        return super(PublicationCreateView, self).form_valid(form)

但是有了这个功能,它只保存了我的表单集中的第一个文档表单:

我查看了 id 文档表单字段,我得到了这个:

第一个标题字段得到id_documents-0-title,但是当我添加更多表单时,标题字段总是得到id_documents-undefined-title

如何从表单集中保存我的文档表单?

谢谢!

编辑:

这是来自@HaiLang 问题的编辑:

这是我的self.request.POST

<QueryDict: {'csrfmiddlewaretoken': ['0LHaaEG1dkyZmOnP3X7037tZI45QrQOIRrQQAMhiOoTyeohDwQdcdTt08yuqH86Z'], 'category': ['23'], 'pub_id': ['PUBSDDD-55'], 'title': ['TESTPUBLIE'], 'description': [''], 'doc-TOTAL_FORMS': ['1'], 'doc-INITIAL_FORMS': ['0'], 'doc-MIN_NUM_FORMS': ['0'], 'doc-MAX_NUM_FORMS': ['4'], 'doc-0-title': ['doc1'], 'doc-0-language': ['FR'], 'doc-0-format': ['pdf'], 'doc-undefined-title': ['doc2'], 'doc-undefined-language': ['FR'], 'doc-undefined-format': ['pdf'], 'doc-__prefix__-title': [''], 'doc-__prefix__-language': [''], 'doc-__prefix__-format': [''], 'doc-__prefix__-upload': ['']}>

这是我的console.log

Element kt.fn.init {}

【问题讨论】:

  • 为了使事情更容易阅读,您应该为您的表单集使用复数。但是,如果 document 是您的表单集,您为什么要为 document 分配一些东西并在 for 循环中保存 document
  • 你在哪一行得到错误?并向我们​​展示您如何构建表单集(您的 get_context_data)
  • @dirkgroten 这是我第一次使用表单集,所以有些事情还不清楚。我在我的问题中添加了get_context_data。问题在线:self.object = form.save()
  • 是使用inlineformset_factory 创建的DocumentFormset
  • 没错!我编辑了我的代码,以便向您展示缺少的元素。

标签: django django-forms formset


【解决方案1】:

幸运的是,我最近刚刚使用过 FormSet,所以我可以看到相关代码的问题。

(由 Ducky 编辑。谢谢!)

您必须在您的views.py 文件和您的app.js 文件之间设置相同的prefix。因为在您的视图文件中您使用的是prefix='doc' 而在您的javascript 函数中您使用的是form 前缀。

所以在你的 JQuery 文件中你必须写:

(function ($) {
$('#add_more').click(function () {
    var form_idx = $('#id_doc-TOTAL_FORMS').val();
    // For debugging the issue
    // console.log('Element', $('#id_doc-TOTAL_FORMS'), 'Num of forms', form_idx);
    $('#form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
    $('#id_doc-TOTAL_FORMS').val(parseInt(form_idx) + 1);
    console.log('Element', $('#id_doc-TOTAL_FORMS'));
});
})(jQuery)

你可以像这样覆盖你的视图:

class PublicationCreateView(CreateView):
    """ Create publication with document form through formset """
    model = Publication
    template_name = 'publication_form.html'

    def get_context_data(self, **kwargs):
        context = super(PublicationCreateView, self).get_context_data(**kwargs)
        document_queryset = Document.objects.all()
        context['DocumentFormSets'] = DocumentFormSet(self.request.POST or None, self.request.FILES or None, prefix='doc', queryset=document_queryset)
        return context

    def form_valid(self, form):
        context = self.get_context_data()
        formsets = context['DocumentFormSets']
        // For debugging
        // print(self.request.POST)
        if form.is_valid() and formsets.is_valid():
            self.object = form.save()
            formsets.instance = self.object
            formsets.save()
        return super(PublicationCreateView, self).form_valid(form)

【讨论】:

  • 感谢您的回答。但我有一些黑点:第一个,控制台中的打印是:Num of forms undefined 每次我在我的表单集中添加一个新表单。我必须看看为什么它被定义为undefined。然后根据您的意见部分,如果我一次保存所有内容,它只会保存我的表单集中的第一个表单。如果我尝试一一保存,它不会保存任何文档。
  • 所以控制台中的Num of forms undefined 确认错误在form_idx。现在可以将脚本更新为console.log('Element', $('#id_form-TOTAL_FORMS'));,即确认 management_form 中的输入可以检索。 $ 符号是 jQuery 的特征。您是否在 HTML 标头中包含 jQuery 脚本?
  • 关于保存表单,能否请您将print(self.request.POST) 放在formsets = 之前并提供输出?那就是确认发布的数据有足够的表格。我相信声明 $('#id_form-TOTAL_FORMS').val(parseInt(form_idx) + 1); 没有完成更新表格总数的工作。
  • 下面是我在生成的 HTML 文件中的 management_form。它具有javascript所需的id_form-TOTAL_FORMS。您能否在生成的 HTML 文件中提供相同的内容? &lt;input type="hidden" name="form-TOTAL_FORMS" value="4" id="id_form-TOTAL_FORMS" /&gt;&lt;input type="hidden" name="form-INITIAL_FORMS" value="1" id="id_form-INITIAL_FORMS" /&gt;&lt;input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS" /&gt;&lt;input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS" /&gt;
  • 能否将 javascript 中的 id_form-TOTAL_FORMS 更新为 id_doc-TOTAL_FORMS?那是因为在你的 management_form 中,它使用 doc 而不是 form
猜你喜欢
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 2016-05-22
  • 2023-04-02
  • 2021-10-10
  • 2014-03-24
相关资源
最近更新 更多