2016-07-25 33 views
0

我有一个表单,利用从我创建的formset的选择参数。当包含formset的页面被渲染时,使用选择参数的字段显示下拉选择小部件。用户填写的表单没有错误。但是,用户未填写的表单对于除了使用选择小部件的字段以外的所有其他字段具有“此字段是必需的”错误。Django formset错误:选择字段导致部分填充的表单

看起来,选择字段的初始值导致表单被视为半填充形式,因此表单验证过程会为未填充的必填字段抛出错误。

# Form: 
class OwnerForm(forms.Form): 
    name = forms.CharField(label = 'Name', max_length = 20) 
    owner_entity = forms.ChoiceField(label = 'Owner Entity', choices = OWNER_ENTITIES) 
    num_of_shares = forms.DecimalField(label = 'Number of Shares' , min_value = 0.0, max_digits = 5, decimal_places = 2) 
    share_class = forms.ChoiceField(label = 'Share Class', choices = SHARE_CLASSES) 
    joined_date = forms.DateField(label = 'Joined Date', help_text = 'mm/dd/yyyy') 

# View: 
# In Get method: 
OwnersFormSet = formset_factory(OwnerForm, extra = 5) 
... 

# In Post method: 
the_owners_forms = OwnerFormSet(request.POST) 

if not the_owners_forms.is_valid(): 
    the_owners_forms_errors = the_owners_forms.errors 

所以,问题是我该如何处理这种行为以使非填充形式不采取是因为选择方法的初值为HAL-填写的表格?

+0

我曾尝试发布问题之前,但它没有奏效。我向OWNER_ENTITIES添加了一个(None,'------------'),但是它跳过了这个并选择元组中的下一个元素。我在想的是手动删除这些初始值,当我收到表单并在手动修改后运行is_valid。 – EarlyCoder

+0

如果您想使用javascript,我为您的问题提供了更加优雅的解决方案 – trantu

+0

您的解决方案非常值得欢迎!我也想知道如何使用Django解决这个问题。 – EarlyCoder

回答

0

我解决的办法,这是一个一点变通。但是,它的工作。

以下是问题: 看起来,选择字段的初始值导致表单被视为半填充形式,因此表单验证过程会为未填充的必填字段抛出错误。

这里是解决方案: 只需复制从真正填充的表单中收到的所有数据,而不是复制带有可供选择的字段的表单,而不是真正由用户填充的表单。然后,重建ManagementForm:

formset_data = {'form-TOTAL_FORMS': total_forms, 
       'form-INITIAL_FORMS': initial_forms , 
       'form-MAX_NUM_FORMS': max_num_forms, 
       } 

# Selectively get the data from the formset of the get request and build 
# correct data into the formset_data by updating it: 
for form in formset: 
    # formset_data.update(<the correct data>) 

OwnersFormsetCopy = formset_factory(form = OwnerForm, extra = extra_forms)   
owners_formset_copy = OwnersFormsetCopy(formset_data) 

# Then, run is_valid() on the new formset to take advantage of 
# Django's form validation utility 
0

你的forms.py怎么样?

默认情况下,您的选择字段将具有'------'作为值,并且在处理表单时将被视为无效。

EMPTY_CHOICE = ((None, '-------------),) 

class OwnerForm(forms.Form): 
    ... 
    owner_entity = forms.ChoiceField(label = 'Owner Entity', choices = EMPTY_CHOICE + OWNER_ENTITIES) 
    ... 
    share_class = forms.ChoiceField(label = 'Share Class', choices = EMPTY_CHOICE + SHARE_CLASSES) 
+0

请在原帖子中查看我的评论:\t 我在发布问题之前尝试过,但没有奏效。 – EarlyCoder

0

所以,这个解决方案是与javascript结合。所以,你不应该使用extra=5有更多的形式。您可以使用“添加更多”按钮,如果你想增加一个形式:

在template.html:

{{ the_owners_forms.management_form }} 
{% for form in the_owners_forms.forms %} 
    <div class='table'> 
    <table class='no_error'> 
     {{ form.as_table }} 
    </table> 
    </div> 
{% endfor %} 
<input type="button" value="Add More" id="add_more"> 
<script> 
    $('#add_more').click(function() { 
     cloneMore('div.table:last', 'form'); 
    }); 
function cloneMore(selector, type) { 
    var newElement = $(selector).clone(true); 
    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); 
} 
</script> 

让我们尝试...