如何使用django formset动态删除对象

问题描述 投票:0回答:1

Django说,我应该这样渲染inline formset

{{ formset.management_form }}
{% for form in formset %}
    {{ form.id }}
    {{ form.field_1 }} 
    {{ form.field_2 }}
    <button type="button"> delete </button>
{% endfor %}
<button type="submit"> submit </button>

好。但是,如果我想动态删除一些formset对象(form)呢?用户按delete按钮 - 我从DOM中删除form,我使用ajax删除对象,与DATABASE中的form相关。它工作正常,直到这一点。但是当用户点击submit时 - 我的views.py尝试验证formset:

filled_formset = OrderItemFormSet(request.POST, instance=order)
if filled_formset.is_valid():

并引发错误:

MultiValueDictKeyError at /order/cart/  
"'orderitem_set-0-id'"  
...\market\ordersys\views.py in show_cart  
59.   if filled_formset.is_valid():

我认为它发生了因为form对象由django显示有一些规律性(第一种形式得到id = orderitem_set-0-id,第二次= orderitem_set-1-id等)当我从DOM中删除第一个form时,规律性被打破 - 没有更多formorderitem_set-0-id 。但is_valid()仍然试图让它dict["orderitem_set-0-id"]

我可以使用一些黑魔法,替换django的技术信息,显示在DOM中,恢复中断的规律性,但有更好的方法吗?

你能告诉我如何正确地动态删除formset项吗?

python django django-forms inline-formset
1个回答
2
投票

我有一段时间没有答案,所以我没有找到比下面更好的解决方案。也许某些人会发现它很有用。

好的,诀窍是 - 在模板中的{{form.DELETE}}中为任何form设置formset。它呈现为一个复选框(我让它变得不可见),每当用户按下“删除”按钮时,我就会使JS“检查”。在用户按下“提交”按钮后,标记为删除的每个form将不会在filled_formset.is_valid()期间由视图验证。这使您可以使用场景后面的ajax从数据库中删除对象。

问题是在formset验证期间引发了ERROR。由对象的形式引起的,该对象已使用ajax从数据库中删除。

所以有所有组件:

views.朋友

def show_cart(request):
    OrderItemFormSet = inlineformset_factory(Order, OrderItem, form=OrderItemForm, extra=0, can_delete=True)
    order = Order.objects.get(pk=request.session['order'])

    if request.method == 'GET':                                                                  
        formset = OrderItemFormSet(instance=order)
        return render(request, 'ordersys/cart.html', {'formset': formset})

    elif request.method == 'POST':            
        filled_formset = OrderItemFormSet(request.POST, instance=order)
        if filled_formset.is_valid():                
            filled_formset.save()
            return redirect('catalog:index')
        else:
            return render(request, 'ordersys/cart.html', {'formset': filled_formset})

cart.html

<form action="" method="post">
    {{ formset.management_form }}
    {% for form in formset %}
        {{ form.id }}
        {{ form.DELETE|add_class:"not_displayed" }}                   # custom filter
        <img src="{{ form.instance.spec_prod.product.picture.url }}">
            {{ form.quantity.label_tag }}
            {{ form.quantity }}
            {{ form.errors }}
            <button type="button">Delete</button>
    {% endfor %}
    <button type="submit">Submit</button>
</form>

接下来,如果用户按“删除”按钮,我的JavaScript 1.用form隐藏$(item).css('display', 'none'); 2.使用form.DELETE制作ItemDelCheckbox.prop('checked', true);复选框 3.发送ajax请求以从数据库中删除项目(否则,如果用户刷新页面,该项目仍在购物车中)

views.朋友

def delete_order_item(request):            # meets the ajax request
    item_id = int(request.POST['item_id'])
    order = get_object_or_404(Order, pk=int(request.POST['order_id']))
    order.remove_item(item_id)
    if order.is_empty():                   # if the last item is deleted
        order.untie(request.session)
        order.delete()
    return HttpResponse()
© www.soinside.com 2019 - 2024. All rights reserved.