首页 文章

从模型formset django动态删除表单

提问于
浏览
7

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

我已阅读Dynamically adding a form to a Django formset with Ajax,基于此我可以动态地将表单添加到formset . 现在我想动态删除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和form2)

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

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 回答

  • 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
    

相关问题