Django内联formset - 允许空白动态生成表单

时间:2012-03-07 17:07:20

标签: django django-forms

我正在使用内联formset和一些javascript来按下按钮添加更多表单。 其中一个视图不断尝试验证空白,动态添加的表单,并触发“此字段是必需的”警告。我对通过extra=2创建的formset中的初始2个表单没有任何问题,它们可以为空而不会导致错误。

OrderLineItem拥有Order

的外键
#views.py
def my_new_form_view(request):
    OrderFormSet = inlineformset_factory(Order, OrderLineItem, extra=2, can_delete=False,
                       formfield_callback=make_custom_datefield, form=OrderLineItemForm,
                       formset=OrderLineFormSet)
    if request.method == 'POST':
        form = OrderForm(request.POST)
        order_formset = OrderFormSet(request.POST, prefix="lineitem")
        if form.is_valid() and order_formset.is_valid():
            new_order = form.save()
            new_order_formset = order_formset.save(commit=False)
            order = Order.objects.get(pk=new_order.pk)
            for form in order_formset.forms:
                if form.has_changed():
                    new_f = form.save(commit=False)
                    new_f.order = order
                    new_f.save()
            return redirect() #go to details 
    else:
        form = OrderForm()
        order_formset = OrderFormSet(prefix='lineitem')

-

#forms.py
class OrderLineFormSet(forms.models.BaseInlineFormset):
    def clean(self):
        #just a clean method to look for duplicates

class OrderLineItemForm(ModelForm):
    #just some callbacks, widget setttings, and the Meta

-

#html
<!-- form stuff above this -->
{{ order_formset.management_form }}
{{ order_formset.non_form_errors }}
{% for form in order_formset %}
<div class="line_item">
    <p>&nbsp;</p>
    {{ form.non_field_errrors }}
    {% for field in form.visible_fields %}
    <div class="field">
        {{ field.errors }}
        {{ field.label_tag }}
        {{ field }}
    </div>
    {% endfor %}
    {% for hidden in form.hidden_fields %}
    {{ hidden }}
    {% endfor %}
</div>
{% endfor %}

$('#add_more').click(function() {
    cloneMore('div.line_item:last', 'lineitem');
}); 

-

#js CloneMore
function cloneMore(selector, type) {
    var newElement = $(selector).clone();
    var total = $('#id_' + type + '-TOTAL_FORMS').val();
    newElement.find(':input').each(function() {
        var name = $(this).attr('name').replace('-' + (total-1) + '-','-' + total + '-');
        var id = 'id_' + name;
        $(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
    });
    newElement.find('label').each(function() {
        var newFor = $(this).attr('for').replace('-' + (total-1) + '-','-' + total + '-');
        $(this).attr('for', newFor);
    });
    total++;
    $('#id_' + type + '-TOTAL_FORMS').val(total);
    $(selector).after(newElement);
}

我会根据要求添加更多代码,这已经非常混乱了。

使用javascript添加表单的某些内容似乎会触发.has_changed(),尽管它是空白的。我错过了哪些不允许空白表格?


解决方案

formset中的一个字段具有默认值。当我克隆表单时,它会清除所有输入。 Django看到删除默认值为更改并触发is_changed()并验证表单。

1 个答案:

答案 0 :(得分:3)

检查生成的表单代码,如Firebug。如果任何字段具有值,则表单将被视为“已填写”,因为它将尝试对其进行验证。即使您使用默认值隐藏字段,也可能发生这种情况。对于要忽略的表单,提交时必须完全空白。