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

标签 python django django-forms inline-formset

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>

好的。但是如果我想动态删除一些表单集对象(form)怎么办?用户按下 delete 按钮 - 我从 DOM 中删除 form,我使用 ajax 从数据库中删除与 form 相关的对象。到目前为止它工作正常。但是当用户点击 submit - 我的 views.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():

我认为这是因为 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 中为任何 form 设置 {{form.DELETE}}。它呈现为一个复选框(我使其不可见),并且每当用户按下“删除”按钮时,我都会让 JS 使其“被选中”。用户按下“提交”按钮后,每个标记为删除的 form 将不会在 filled_formset.is_valid() 期间被 View 验证。这使您可以在后台使用 ajax 从数据库中删除对象。

The problem was that an ERROR was raised during formset validation. Caused by the form of an object, which was already deleted from database with ajax.

所以有所有组件:

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

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>

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

views.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()

关于python - 如何使用 django formset 动态删除对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47954063/

相关文章:

java - 如何在 Java 中为 TensorFlow DNNRegressor 提供输入?

python - 在 Django 管理中将外键列显示为指向详细信息对象的链接

python - Django View 中的 "request"是什么

python - 如何覆盖动态创建的类实例的方法

python - Django Admin 显示外键值

python - 向文章 django createviewforeignkey 添加评论

python - Django 管理表单字段 - 在选择框中显示对象相关的查询结果

Django:验证多个字段

django - 在 Pycharm 中调试表单验证

Python:具有简单解决方案的多边形形状文件中的轮廓特征