我有一个网页,用户可以动态添加和删除表单到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。
任何人都知道我在这里失踪了什么?或者更好的方法来做到这一点。
如何动态删除表单集中的表单,因为表单的顺序似乎应该是顺序的。
先谢谢!!任何帮助表示赞赏。
答案 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