django表单集无法验证,因为需要ID

Big*_*gga 5 forms django validation formset

我的视图从模板接收到一个模型表单集,但未通过验证,声称需要ID。到目前为止,我对表格的使用从未提出过这个问题,而且我也从未传递过ID。

这是我的观点的简化版本:

def BudgetView(request):

    import pdb
    pdb.set_trace()

    if request.user.is_authenticated:
        U=request.user

        #initalize formset factories
        ItemFormSet = modelformset_factory(Item, fields=(blabla), extra=0)
        CatFormset=modelformset_factory(BudgetCatagory, fields=(blabla), extra=0)

        #initalize Constants
        InitiateConstants(CatagoryItemsList)

        if request.method=='POST':
            FormsetItem=ItemFormSet(request.POST,initial=Item.objects.filter(budgetcatagory__user_id=U.id).values())
            FormsetCat=CatFormset(request.POST)
            if FormsetItem.is_valid():
-bla
-bla
-bla

            return redirect('/HighLevelInput')
        else:
            #populate
            I=Item.objects.filter(budgetcatagory__user_id=U.id)
            C=BudgetCatagory.objects.filter(user_id=U.id)

            #initiate initial catagories and items for new user
            if (not I.exists()) or (not C.exists()):
                Item.objects.filter(budgetcatagory__user_id=U.id).delete()
                BudgetCatagory.objects.filter(user_id=U.id).delete()
                InitiateNewUser(U)
                I=Item.objects.filter(budgetcatagory__user_id=U.id)
                C=BudgetCatagory.objects.filter(user_id=U.id)
            FormsetItem=ItemFormSet(queryset=I)
            FormsetCat=CatFormset(queryset=C)

        return render(request,'getdata/budgetmachine.html', {'FormsetItem':FormsetItem, 'FormsetCat':FormsetCat })
    else:
        return redirect('/login')
Run Code Online (Sandbox Code Playgroud)

由于上面提到的原因,is_valid返回FALSE。有任何想法吗?

根据要求,以下是is_valid检查返回的错误:

(Pdb) FormsetItem.errors
[{'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'name': ['This field is required.'], 'detail': ['This field is required.'], 'layout': ['This field is required.'], 'unit': ['This field is required.'], 'unit_description': ['This field is required.'], 'parent': ['This field is required.'], 'enName': ['This field is required.'], 'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'name': ['Ensure this value has at most 30 characters (it has 32).'], 'parent': ['Ensure this value has at most 30 characters (it has 32).'], 'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}]
Run Code Online (Sandbox Code Playgroud)

这是我的模板:

{% block body %}

<div class="container" style="width:80%">

  <form method="post">
    {% csrf_token %}
    {{ FormsetItem.management_form }}
    {{ FormsetCat.management_form }}

    <table>
      <tr>
        <th>????</th>
        <th>???? ??????</th>
        <th>????? ????</th>
        <th>??? ?????</th>
        <th>??? ?????</th>
      </tr>

      <!--unpacks the item dictionary into formsets -->
      {% for CatForm in FormsetCat %}
        <tbody onmouseenter="ToggleDisable('{{ CatForm.enName.value}}')" onmouseleave="ToggleDisable('{{ CatForm.enName.value}}')">
          {% for ItemForm in FormsetItem %}
            {% if ItemForm.parent.value == CatForm.name.value %}
                {% if ItemForm.layout.value == 'normal' %}
                  {% include 'getdata/normalBudgetLayout.html' with form=ItemForm itemCount=forloop.counter0 catagoryCount=forloop.parentloop.counter0 %}
                {% elif ItemForm.layout.value == 'choice' %}
                  {% include 'getdata/choiceBudgetLayout.html' with form=ItemForm itemCount=forloop.counter0 catagoryCount=forloop.parentloop.counter0 %}
                {% endif %}
            {% endif %}
          {% endfor %}
        <tr class="txt_center Row_{{ CatForm.enName.value}}" style="line-height:4em; background:Silver;">
          <td>
            <a onclick="ToggleDisable('{{ CatForm.enName.value}}')">
              {{ CatForm.name.value }}
              <span style="float:left;">
                <i class="fa fa-caret-down {{ CatForm.enName.value}}" style="font-size:30px; padding:7px;"></i>
                <i class="fa fa-caret-up {{ CatForm.enName.value}}" style="font-size:30px; padding:7px;" hidden></i>
              </span>
            <!--/a-->
          </td>
          <td>{{ CatForm.catagory_cost }}</td>
          <td>TBD</td>
          <td>{{ CatForm.detail.value }}</td>
          <td></td>
        </tr>
        </tbody>
      {% endfor %}
    </table>
    <br />
    <br />
    <br />
    <button type="submit" >Submit</button>    <br />
    <br />

  </form>
</div>




{% endblock %}
Run Code Online (Sandbox Code Playgroud)

谢谢

Car*_*ker 8

ModelFormsets要求form.id。它呈现为隐藏字段。您将需要使用两个表单集来实现它。

{% for form in formset %}
    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}
    <!-- form.visible fields go here -->
{% endfor %}
Run Code Online (Sandbox Code Playgroud)


J-a*_*u-s 5

作为@unixo 答案的附录,简单地说:

{{ form.id }}
Run Code Online (Sandbox Code Playgroud)

没有任何周围的 HTML 标记,将在呈现模板时转换为以下内容( 的值namevalue并且id将由您的 生成formset_factory):

<input type="hidden" name="form-1-id" value="2" id="id_form-1-id">
Run Code Online (Sandbox Code Playgroud)

只要确保它缩进for form in formset循环即可。

这意味着您不需要添加,class="hidden"除非您对所需的隐藏字段有一些特殊处理。


uni*_*ixo 3

在这种情况下,错误消息非常清楚:您必须呈现“id”字段,否则 POST 将不会包含每个记录的主键值。

我建议使用脆皮表单并让它呈现整个表单集或手动呈现模板中的字段。在第一种情况下,你会得到这样的结果:

{% load crispy_forms_tags %}
<form action="post" ...>
    {% crispy formset %}
</form>
Run Code Online (Sandbox Code Playgroud)

否则:

<form action="post" ...> 
    <table>
        <tbody>
           {% for form in formset %}
           <tr>
              <td>{{ form.field1 }}</td>
              <td>{{ form.field2 }}</td>
              <td class="hidden">{{ form.id }}</td>
           </tr>
        </tbody>
    </table>             
</form>
Run Code Online (Sandbox Code Playgroud)