代码之家  ›  专栏  ›  技术社区  ›  cMeIIIHo

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

  •  2
  • cMeIIIHo  · 技术社区  · 7 年前

    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 按钮-i删除 类型 从DOM中,我使用ajax删除与 类型 从数据库中。到目前为止一切正常。但当用户点击 submit -我的观点。py正在尝试验证表单集:

    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():
    

    我想这是因为 类型 django以某种规律性显示对象(第一种形式是获得id= orderitem_set-0-id ,秒= orderitem_set-1-id 当我第一次删除时 类型 从DOM开始,规律性就被打破了——再也没有了 类型 具有 orderitem\u集-0-id . 但是 is_valid() 仍在努力 dict["orderitem_set-0-id"] .

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

    您能告诉我如何正确地动态删除表单集项目吗?

    2 回复  |  直到 7 年前
        1
  •  5
  •   cMeIIIHo    7 年前

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

    好吧,诀窍在于 {{form.DELETE}} 对于任何 form 在您的 formset 在模板中。它呈现为一个复选框(我使其不可见),我使JS使其在用户按下“删除”按钮时处于“选中”状态。用户按下“提交”按钮后 类型 ,标记为删除,在 filled_formset.is_valid() . 这允许您在后台使用ajax从数据库中删除对象。

    问题是在表单集验证期间出现错误。由对象的形式引起,该对象已使用ajax从数据库中删除。

    因此,有所有组件:

    意见。py公司

    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})
    

    运货马车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、隐藏 类型 具有 $(item).css('display', 'none');
    2、进行检查 form.DELETE 带有的复选框 ItemDelCheckbox.prop('checked', true);
    3、发送ajax请求从数据库中删除项目(否则,如果用户刷新页面,项目仍在购物车中)

    意见。py公司

    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()
    
        2
  •  1
  •   Chris Sam    4 年前

    与使用{form.DELETE}}手动创建隐藏字段不同,您可能可以在实例化formset时使用“can\u DELETE”,而formset也会这样做。对于eg,

    ArticleFormSet = formset_factory(ArticleForm, can_delete=True)
    

    参考 can_delete