Django formset错误:选择字段导致部分填充的表单

时间:2016-07-25 14:44:03

标签: django forms django-forms django-views

我有一个使用选择参数的表单,我已经从中创建了一个formset。呈现包含formset的页面时,使用choices参数的字段显示下拉选择窗口小部件。用户填写的表单没有错误。但是,未由用户填写的表单具有'此字段是必需的'除了使用select小部件的字段之外的所有其他字段的错误。

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

# 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

所以,问题是如何处理这种行为,以便由于select方法的初始值,未填充的表单不会被视为hal-filled表单?

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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>

试试......

答案 2 :(得分: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