如何添加多行的Formset?

时间:2019-08-13 14:04:48

标签: django python-3.x django-forms

我为用户制作表格。 他们必须以适当的形式添加许多模型对象。 进入GET方法时显示一行 他们将输入输入名称=“ add-rows-number”,该数字应显示在表单集中的表单数

我尝试使用formset和模型formsetfactory

class AddCostCenters(View):

    def __init__(self, *args, **kwargs):
        super(AddCostCenters, self).__init__(*args, **kwargs)
        self.FormSet = modelformset_factory(CostCenter, form=CostCenterAddForm, extra=self.get_form_size)


    def get_form_size(self, request):
        extra_rows_num = 1
        if 'add-rows' in request.POST:
                extra_rows_num += int(request.POST.get('add-rows-number'))
        return extra_rows_num

    def get(self, request, proceeding_id):
        costcenter_model = CostCenter.objects.filter(
            participation__provider__user=request.user,
            participation__proceeding=proceeding_id
        )

        return TemplateResponse(request, 'costcenteradd.html', context)

    def post(self, request, proceeding_id):
        costcenter_model = CostCenter.objects.filter(
            participation__provider__user=request.user,
            participation__proceeding=proceeding_id
        )

        # if 'add-rows' in request.POST:
        #     try:
        #         rows_to_show = int(request.POST.get('add-rows-number'))
        #     except ValueError:
        #         rows_to_show = 0
        #     self.extra_rows_number += rows_to_show


        if 'save_form' in request.POST:
            new_cost_centers = []
            post_formset_data = self.FormSet(request.POST)

            if post_formset_data.is_valid():
                instances = post_formset_data.save(commit=False)
                new_cost_centers.append(instance)
                        # do something

            else:
                post_form = post_formset_data


        context = {
            'form': post_form,
        }
        return render(request, 'costcenteradd.html', context)

表格

 class CostCenterAddForm(forms.ModelForm):
    # helper = CostCenterAddFormSetHelper()

    def __init__(self, *args, **kwargs):
        super(CostCenterAddForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_show_labels = False

        for field_name, field in self.fields.items():
            field.help_text = None

    class Meta:
        model = CostCenter
        fields = (
            'id',
            'cost_center_account_no',
            'cost_center_account_name',
            'departmental_code',
            'values_for_year',
            'only_total_cost_of_cost_center',
        )
        exclude = (
            'participation',
            'to_check',
            'is_checked',
            'accepted',
            'use_in_calculations',
        )

html

<div class="container-fluid ">
      <form method="post">
          {% csrf_token %}
          {{ form.management_form }}
                <div class="row sticky-top text-center form-nav">
                    <div class="col-md-2 content_center"> Numer Konta OPK </div>
                    <div class="col-md-4 content_center"> Nazwa konta OPK </div>
                    <div class="col-md-2 content_center"> Kod resortowy  </div>
                    <div class="col-md-1 content_center"> Rok za który jest postępowanie </div>
                    <div class="col-md-1 content_center"> Uproszczone dane finansowe </div>
                    <div class="col-md-2 content_center"> Usuń </div>
                </div>
                <div class="section sticky-top my-2 form-panel ">
                    <div class="row sticky-top my-2">
                        <div class="col-md-2">
                            <button class="btn btn-success btn-block" type="submit" name="save_form">Zapisz</button>
                        </div>
                        <div class="col-md-4">
                            <div class="input-group mb-3">
                                <input class="form-control" min="1" type="number" name="add-rows-number"
                                value={{form.total_form_count }}
                                placeholder="number" aria-label="add form rows ">
                                <div class="input-group-append">
                                    <button class="btn btn-info" type="submit" name="add-rows">show_rows</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
      <hr>
            {% for field in form %}
            <div class="row text-center">
                <div class="col-md-2 paste-in">
                {{field.cost_center_account_no | as_crispy_field}}
                </div>
                <div class="col-md-4 paste-in">
                {{field.cost_center_account_name | as_crispy_field}}
                </div>
                <div class="col-md-2 paste-in">
                {{field.departmental_code | as_crispy_field}}
                </div>
                <div class="col-md-1 paste-in">
                {{field.values_for_year | as_crispy_field}}
                </div>
                <div class="col-md-1">
                {{field.only_total_cost_of_cost_center | as_crispy_field}}
                </div>
                <div class="col-md-2">
                <input type="submit" name="del_btn{{ field.instance.id }}" value="del"
                       {% if field.instance.id == None %}
                        class="btn btn-outline-secondary" disabled
                       {% else %}
                        class="btn btn-outline-danger"
                       {% endif%} />
                </div>
            </div>

1 个答案:

答案 0 :(得分:0)

您需要同时在formsetget()方法中创建post()并将其添加到上下文中。您使用queryset属性用现有实例填充它:

formset = self.FormSet(queryset=CostCenter.objects.filter(...))
# or
formset = self.FormSet(queryset=CostCenter.objects.filter(...), data=request.POST)

然后在您的模板中,循环浏览formset(在模板中称为form的实际上是一个表单集):

{{ formset.management_form }}
{% for form in formset %}
    {{ form.cost_center_account_no|as_crispy_field }}
    ...
{% endfor %}

在您对self.FormSet的定义中,设置extra=1,以便用户至少有一个额外的行。删除计算,因为这不起作用。 request__init__()的{​​{1}}中不可用(它与View一起添加)。

现在,我不会让用户提交额外的行数,您只需从输入数据中扣除它即可。编写一些JavaScript,让用户自己直接添加行,就像在管理员中看到的那样:

  • 添加+按钮以添加额外的行
  • javascript会克隆上一行,并将其添加到表单列表中(输入字段为空)
  • javascript还会更新TOTAL_FORMS和MAX_FORMS输入字段(管理表单中的隐藏字段)的值

这样,当用户提交表单集时,它将有多余的行。