Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django modelformset\u工厂删除标记为删除的模型表单_Django_Django Forms - Fatal编程技术网

Django modelformset\u工厂删除标记为删除的模型表单

Django modelformset\u工厂删除标记为删除的模型表单,django,django-forms,Django,Django Forms,使用modelformset_factory时,如何从数据库中删除表单中标记为删除的对象 我创建的modelformset_工厂如下所示: ItemFormset = modelformset_factory(Item, ItemModelForm, extra=1, can_delete=True) qset = Item.objects.filter(pr=pr) formset = ItemFormset(queryset=qset) if request.method=="POST":

使用modelformset_factory时,如何从数据库中删除表单中标记为删除的对象

我创建的modelformset_工厂如下所示:

ItemFormset = modelformset_factory(Item, ItemModelForm, extra=1, can_delete=True)
qset = Item.objects.filter(pr=pr)
formset = ItemFormset(queryset=qset)
if request.method=="POST":
    formset = ItemFormset(request.POST)
    if formset.is_valid():
        # Save, delete, update ..everything you need in one command:
        instances = formset.save()

        for instance in instances:
            # Make sure the assigned pr hasn't changed
            if instance.pr != pr:
                instance.pr = pr 
                instance.save()
当表单集返回帖子时,我得到如下数据:

if request.method == "POST":
    formset = ItemFormset(request.POST,queryset=qset)
    if  formset.is_valid():
        marked_for_delete = formset.deleted_forms
        instances = formset.save(commit=False)
        for item in instances:
            item.pr = pr
            item.save()
当表单集返回时,我可以使用
formset.deleted\u forms
获取所有标记为删除的对象,但我不知道如何实际删除它们。我已尝试循环遍历每个对象并逐个删除每个对象,但出现错误:
Item对象无法删除,因为其id属性设置为None。

在模板中,我包含了
{{form.id}
,因此每个对象都有它的id,并在POST中传回

调用
instances=formset.save(commit=False)
后,我可以调用
formset.deleted\u objects
,但它只是一个空列表:
[]


有人能看到我做错了什么,使对象无法从数据库中删除吗?

通过将项目模型中的所有字段包含在ItemModelForm中,我可以调用
formset.save()
,表单中标记为删除的所有模型都会被删除,修改或添加的任何模型都会得到更新或保存。我将字段“pr”(外键)作为HiddenInput,并通过扩展ItemModelForm将其初始化,如下所示:

class EnhancedItemForm(ItemModelForm):
    def __init__(self, *args, **kwargs):
        super(EnhancedItemForm, self).__init__(*args, **kwargs)
        self.fields['pr'].widget = forms.HiddenInput()
        self.fields['pr'].initial = pr
ItemFormset = modelformset_factory(Item, EnhancedItemForm, extra=extra_forms, can_delete=True)
formset = ItemFormset(queryset=qset)
然后我可以像这样处理这个帖子:

ItemFormset = modelformset_factory(Item, ItemModelForm, extra=1, can_delete=True)
qset = Item.objects.filter(pr=pr)
formset = ItemFormset(queryset=qset)
if request.method=="POST":
    formset = ItemFormset(request.POST)
    if formset.is_valid():
        # Save, delete, update ..everything you need in one command:
        instances = formset.save()

        for instance in instances:
            # Make sure the assigned pr hasn't changed
            if instance.pr != pr:
                instance.pr = pr 
                instance.save()

由于modelformset_工厂接受ModelForm类而不是ModelForm的实例,因此我必须在视图中扩展ItemModelForm,在该视图中我知道要将pr初始化为什么

让您困惑的是
formset.save(commit=False)
并没有做您认为它能做的事情

虽然设置了
commit=False
时,编辑的对象不会
save()
d,但令人困惑的是,删除的对象会被删除

因此,在调用
save(commit=False)
后,当您循环调用
标记为_for _delete
时,您得到的对象已经被删除,因此它们的id为
None

你的自我回答会更好,更地道;通常,只需调用
formset.save()
,并将其默认设置为
commit=True
。事实上,
commit=False
案例相对较少且被废弃,这可能是没有人修复删除对象的(IMO,bug)行为的原因

(顺便说一句,我只在非事务性/自动提交数据库环境中观察到了这种行为;这可能是由于启用了
commit=False
和事务,您在删除方面获得了更健壮的行为。)

注意:这种行为在Django 1.7中已经发生了改变:

如果调用formset.save(commit=False),对象将不会自动删除。您需要对每个formset.deleted_对象调用delete(),才能真正删除它们


我想问题在于commit=False。“公关”是一个模型领域吗?如果是这样,您可以将它映射到HiddenInput,而不是excuding,确保它位于表单集的init()或save()上,尽管使用通常的committeing formset.save()ilvar,但我尝试在HiddenField中将pr添加到表单中,而不是将其排除,现在我可以调用
formset.save()
但它只会保存提交的表单,而不会从数据库中删除标记为删除的表单。这也会导致每个未标记为删除的表单出现重复的数据库条目(它不会修改当前条目,它只会创建新条目,而不管对当前条目的修改如何,都会创建新条目)。好的,在隐藏字段中设置pr实际上起到了作用(我不得不从以前的工作中删除一些破坏它的旧javascript),但我不知道如何将pr分配给空表单或额外表单的初始值。当我尝试这样设置时:
formset.initial=[{'pr':pr_pk,'quantity':0}]
quantity已初始化,但不是pr。在验证和保存之前,您需要修改formset.data,以避免有人更改隐藏字段值。因此,您根本不需要将其设置为initial(尽管无论小部件类型如何,它都应该工作),我想调用formset.save(commit=False)已经删除了标记为删除的项目。这就是为什么会出现“无”错误。我刚才实现了与您相同的用例,并且调用save(commit=False)并遍历实例,即使有标记为删除的项目,它们也不会导致任何类型的错误。请注意,此行为:如果调用
formset.save(commit=False)
,对象将不会自动删除。您需要对每个
formset.deleted\u对象调用
delete()
,才能真正删除它们