3

Django表单让我绊倒了很多次......

我给一个 ChoiceField 初始值(表单类的init )

self.fields['thread_type'] = forms.ChoiceField(choices=choices, 
    widget=forms.Select, 
    initial=thread_type)  

用上面的代码创建的表单thread_type没有通过 is_valid() 因为“这个字段(thread_type)是必需的”。

-EDIT-
找到了解决方法,但它仍然让我很困惑。

我的模板中有一个代码

   {% if request.user.is_administrator() %}
      <div class="select-post-type-div">                                                                                                                                                                                                                                        
        {{form.thread_type}}                                                                                                                                                                                                                                                    
      </div> 
   {% endif %}

并且当此表单被提交时,当用户不是管理员时,request.POST 没有“thread_type”。

view 函数使用以下代码创建表单:

form = forms.MyForm(request.POST, otherVar=otherVar)

我不明白为什么通过以下(与上面相同)给出初始值是不够的。

self.fields['thread_type'] = forms.ChoiceField(choices=choices, 
        widget=forms.Select, 
        initial=thread_type)  

并且,包含thread_type变量request.POST允许表单通过 is_valid() 检查。

表单类代码如下所示

class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
    title = TitleField()
    tags = TagNamesField()


    #some more fields.. but removed for brevity, thread_type isn't defined here 

    def __init__(self, *args, **kwargs):
        """populate EditQuestionForm with initial data"""
        self.question = kwargs.pop('question')
        self.user = kwargs.pop('user')#preserve for superclass                                                                                                                                                                                                                  
        thread_type = kwargs.pop('thread_type', self.question.thread.thread_type)
        revision = kwargs.pop('revision')
        super(EditQuestionForm, self).__init__(*args, **kwargs)
        #it is important to add this field dynamically     

        self.fields['thread_type'] = forms.ChoiceField(choices=choices, widget=forms.Select, initial=thread_type)
4

1 回答 1

1

不要动态添加此字段,而是在类中适当地定义它:

class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
    title = TitleField()
    tags = TagNamesField()
    thread_type = forms.ChoiceField(choices=choices, widget=forms.Select)

创建表单实例时,如果需要,请设置一个初始值:

form = EditQuestionForm(initial={'tread_type': thread_type})

如果您不需要此字段,只需将其删除:

class EditQuestionForm(PostAsSomeoneForm, PostPrivatelyForm):
    def __init__(self, *args, **kwargs):
        super(EditQuestionForm, self).__init__(*args, **kwargs)
        if some_condition:
            del self.fields['thread_type']

保存表格时,请检查:

thread_type = self.cleaned_data['thread_type'] if 'thread_type' in self.cleaned_data  else None

这种方法对我来说总是很有效。

于 2013-08-20T09:29:08.350 回答