Django表单错误:选择一个有效的选项。 29不是可用的选择之一

时间:2012-05-04 09:38:35

标签: python django django-forms

表单HTML

<form action="" method="post" class="form-horizontal"><div style="display:none"><input type="hidden" name="csrfmiddlewaretoken" value="6b3d58df7bd4f6d10975462aaf3bd42d"></div>
        <input type="hidden" name="paper" value="5225" id="id_paper"><fieldset><div id="div_id_priority" class="control-group">
    <label class="control-label" for="id_priority">Priority</label>
    <div class="controls">
        <select name="priority" id="id_priority">
<option value="1" selected="selected">Primary</option>
<option value="2">Secondary</option>
</select>


        <p class="help-block"><span class="help_text">Primary - 1st Choice. Secondary - 2nd Choice.</span></p>

    </div>
</div> <!-- /clearfix -->
<div id="div_id_topic" class="control-group">
    <label class="control-label" for="id_topic">Topics</label>
    <div class="controls">
        <select name="topic" id="id_topic">
<option value="6">A</option>
<option value="7" selected="selected">B</option>
<option value="9">C</option>
</select>


    </div>
</div> <!-- /clearfix -->
<div id="div_id_subtopic" class="control-group error">
    <label class="control-label" for="id_subtopic">SubTopics</label>
    <div class="controls">
        <select name="subtopic" id="id_subtopic">
<option value="29">KEEPER</option></select>

        <span class="help-inline">Select a valid choice. 29 is not one of the available choices.</span>


    </div>
</div> <!-- /clearfix -->
</fieldset>

        <div class="form-actions">
            <button type="submit" class="btn btn-primary">Add</button>
        </div>

    </form>

查看

@login_required
@event_required
def add_topic(request, paper_id):
    event = request.event
    paper = get_object_or_404(SubmissionImportData, pk=paper_id)
    form = TopicForm(request.POST or None, event=event, paper=paper)
    print request.POST  # i see subtopic here
    print form.errors
    if request.method == 'POST' and form.is_valid():
        cd = form.cleaned_data
        subtopic = request.POST.get('subtopic')
        if subtopic:
            subtopic_obj = get_object_or_404(SubTopic, pk=subtopic)
        else:
            subtopic_obj = None

        paper_topic = PaperTopic.objects.get_or_create(
                submission_import_data=paper,
                priority=cd['priority'],
                topic=cd['topic'],
                sub_topic=subtopic_obj)[0]

        msg = 'Topic Successfully Added'
        messages.success(request, msg)
        url = reverse('submissions_nonadmin_view_topic',
                args=[event.slug, paper.id])
        return redirect(url)

FORM CLASS

class TopicForm(BootstrapForm):
    topic = forms.ModelChoiceField(label='Topics',
            queryset=None, required=False, empty_label=None)
    subtopic = forms.ChoiceField(label='SubTopics',
            widget=forms.Select(attrs={'disabled': 'disabled'}),
            required=False)
    paper = forms.IntegerField(widget=forms.HiddenInput())
    priority = forms.ChoiceField(label='Priority',
            choices=PaperTopic.PRIORITY, required=False)

    class Meta:
        fields = (
                'priority', 'topic', 'subtopic', 'paper',
                )
        layout = (
                Fieldset('', 'priority', 'topic', 'subtopic', 'paper',),
                )

    def __init__(self, *args, **kwargs):
        event = kwargs.pop('event')
        #paper_topic = kwargs.pop('paper_topic')
        paper = kwargs.pop('paper')
        super(TopicForm, self).__init__(*args, **kwargs)
        self.fields['paper'].initial = paper.id
        self.fields['topic'].queryset = Topic.objects.\
                filter(setting=event.setting)
        self.fields['priority'].help_text = 'Primary - 1st Choice. Secondary - 2nd Choice.'
        #if paper_topic:
            #self.fields['topic'].initial = Topic.objects.\
                    #get(pk=paper_topic.topic.id)

    def clean(self):
        '''
        Limit topic associations to 2
        '''
        print 111, self.cleaned_data  # subtopic field is missing here
        cleaned_data = self.cleaned_data
        topic = cleaned_data.get('topic', None)
        subtopic = cleaned_data.get('subtopic', None)
        paper = cleaned_data.get('paper', None)
        priority = cleaned_data.get('priority', None)
        paper_obj = get_object_or_404(SubmissionImportData, pk=paper)

        if topic:
            topic_count = PaperTopic.objects.\
                    filter(submission_import_data=paper_obj).count()
            if topic_count >= 2:
                raise forms.ValidationError("You can only select up to two sets of topic and subtopic associations.")

        if PaperTopic.objects.filter(submission_import_data=paper_obj,
               priority=priority).exists():
            raise forms.ValidationError("You have already chosen that priority level.")
        if PaperTopic.objects.filter(submission_import_data=paper_obj,
               topic=topic, sub_topic=subtopic).exists():
            raise forms.ValidationError("You have already chosen that set of Topic and Subtopic association.")
        print 999999000000
        return cleaned_data

当我尝试提交表单时,我收到此错误: <span class="help-inline">Select a valid choice. 29 is not one of the available choices.</span>

我正在根据主题中选择的值通过AJAX动态生成子主题下拉列表的选项。

我可以在subtopic中看到request.POST,但当它到达clean方法时,subtopic字段就会消失。

我不太确定发生了什么......

更新

另一方面,当子主题没有值时,select元素设置为disabled=disabled。当我尝试提交这样的表单时,我可以在我的清洁方法中获得subtopic字段。而当该字段未被禁用时,我无法通过我的干净方法获得它。这就像我期待的相反行为......

1 个答案:

答案 0 :(得分:12)

ChoiceField()需要一系列选项来验证。虽然你这样做 这适用于topic

self.fields['topic'].queryset = Topic.objects.\
                filter(setting=event.setting)

subtopic被初始化为空列表,因此没有选项有效。

您必须使用每个可能的子主题实例初始化self.fields['subtopic'].choices并使用Javascript决定显示/隐藏哪些子主题(取决于选择的主题)。