从模型formset django动态删除表单

时间:2012-09-13 20:26:07

标签: django django-models django-forms

我有一个网页,用户可以动态添加和删除表单到django formsets。

我已阅读Dynamically adding a form to a Django formset with Ajax,基于此我可以动态地将表单添加到表单集。现在我想动态删除formset。我看过Dynamically Delete inline formsets in Django

我想要的方式是当用户点击删除时,我有一个ajax函数,它从数据库中删除表单实例记录。当我的ajax函数返回时,我保持相同的total_form_count和initial_form_count,只隐藏表单html,以便在我的POST中提交已删除的记录。

最初,formset将其表单元素呈现为:

#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">

现在假设我在删除记录后动态删除表单0,使用ajax,我不会更改表单计数,因此total_form_count和initial_form_count是3。

(如果我将total_form_count和initial_form_count减少到2,当我在视图中使用POST数据填充formset时,它应该以form0和form1的形式排序。但在我的情况下,有效的表单是form1和窗口2)

现在在我看来,我做了类似以下的事情来保存我的表格。

myformset = modelformset_factory(ObjectElement,form=Object_Form, extra=0, can_delete=True)
for form in myformset.forms:
    print(form.instance.id) #this does not print id of deleted record, but of the first existing record in the database.
    print(form.instance.attribute)# this prints the correct element, which was submitted by POST even for a deleted record.
    try: 
      objectInstance = ObjectElement.objects.get(id = form.instance.id)
      objectInstance.save()
    except ObjectElement.DoesNotExist:
      print("Do not save as the record has already been deleted")     

当我保存我的formset而不删除任何记录时,保存工作正常并且打印了正确的form.instance.id。 但是,如果我使用ajax删除表单实例,然后尝试保存我的formset,那么 已删除记录的print(form.instance.id)似乎打印了数据库中的第一个可用ID,但不打印post提交的id。 (删除记录时,数据库中不存在id,但是应该打印通过POST提交给它的内容吗?)

如果我没有try / catch循环,我会通过form.errors获得以下错误:

<ul class="errorlist"><li>id<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>

似乎表明它不接受已删除记录的提交帖子中的正确表单ID。

任何人都知道我在这里失踪了什么?或者更好的方法来做到这一点。

如何动态删除表单集中的表单,因为表单的顺序似乎应该是顺序的。

先谢谢!!任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:9)

对于那些偶然发现这个问题的人来说,这可能是一个可能的解决方案 我能够从formset中动态删除我的表单,如下所示。

所以初始形式html看起来像

#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">

现在假设我使用ajax从我的数据库中删除form0和form1记录。 当我提交表单时,formset将不会验证,因为它希望表单按顺序排列,并且我只在数据库中保留了表单2(我删除了前两个)。如问题中所述,使用“选择有效选择”的Formset错误。

因此,在我动态删除表单后,当我的ajax返回时,我不会更改total_form_count,(https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#understanding-the-managementform),而是在html中将表单标记为已删除,只需隐藏表单即可。现在,当使用POST提交formset时,它也会提交已删除的表单,但标记为已删除(https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#can-delete

现在在视图中,我首先筛选出已删除的表单,并仅处理仍保留如下的表单

marked_for_delete = formset.deleted_forms
    for form in formset.forms:
        #Filtering out the deleted records, as the formset will not validate, for deleted records
        # if we use form.instance.id or form.initial['id'] below it does not work. 
        #for some reason it returns the id of the first available record in the data base. 
        #form['id'].value(), gives us the id of the deleted element we are looking for
        if form['id'].value() not in [deleted_record['id'].value() for deleted_record in marked_for_delete]:    
            if form.is_valid():
                pass
                # save the form
            else:
                pass
                # error message