2017-10-20 68 views
0

我想根据外键父模型的字段值设置选项。即“QuestionAnswer”模型外键“问题”被设置为对“问题”建模,并且该模型包含字段“question_type”。如果“question_type”值为1,则将选项设置为a,b,c,d,e或者如果值为2,则将选项设置为f,g,h,i,j。表单构建为formset,但不应该影响它的完成方式?按外键父模型的字段设置选择

首先,我将选项设置为一个功能,我在哪里设置它? Forms.py,models.py或views.py? 如果在forms.py中,我可以用init方法吗? 如何一起获得正确的问题和正确的选择?

如果您需要更多信息,请询问。

Django的版本是1.11.5和Python版本3.6.0

forms.py

class AnswerForm(forms.ModelForm): 
    class Meta: 
     model = QuestionAnswer 
     fields = ['question', 'answer_text', 'questionnaire_key'] 
     exclude = [] 
     widgets = { 
      'question': HiddenInput, 
      'answer_text': RadioSelect(choices=CHOICES, 
               attrs={'required': 'True'}), 
      'questionnaire_key': HiddenInput 
      } 

models.py

class Question(models.Model): 
    questionnaire = models.ForeignKey(Questionnaire) 
    question_text = models.CharField(max_length=200) 
    question_type = models.CharField(max_length=2) 
    def __str__(self): 
     return self.question_text 

class QuestionAnswer(models.Model): 
    questionnaire_key = models.ForeignKey(Questionnaire, null=False, blank=False) 
    question = models.ForeignKey(Question, null=False, blank=False) 
    answer_text = models.CharField(max_length=1, null=False, default=None) 
    def __str__(self): 
     return self.answer_text 

在视图予设定的初始问题数据为formset。我将问题和表单集成到表格中,左侧是问题文本,右侧是答案选项。 views.py

def answerpage(request, questionnaire_pk): 
    AnswerFormSet = formset_factory(AnswerForm, extra=0) 
    questions = Question.objects.filter(questionnaire=questionnaire_pk) 
    qname = Questionnaire.objects.get(id=questionnaire_pk) 

    if request.method == 'POST': 
     answer_formset = AnswerFormSet(request.POST) 
     ... 
    else: 
     quest_id = request.session.get('questionnaire_key', 0) 
     question_data = [{'question': question, 
          'questionnaire_key': quest_id} for question in questions] 

     answer_formset = AnswerFormSet(initial=question_data) 

    combined = zip(questions, answer_formset) 
    context = { 
     'combined': combined, 
     'questions': questions, 
     'answer_formset': answer_formset, 
     'qname': qname, 
    } 
    return render(request, 'main/questionnaire_details2.html', context) 

UPDATE:

窗体的init方法

def __init__(self, *args, **kwargs): 
     extra_info = kwargs.pop('questions', None) 
     super(AnswerForm, self).__init__(*args, **kwargs) 
     self.fields['answer_text'].widget = RadioSelect() 
     self.fields['answer_text'].choices = get_choice_data(self.instance, extra_info) 

设置在这里form_kwargs:

formset = AnswerFormSet(form_kwargs={'questions': questions})

如何使用formset?如果我用answer_formset = formset(initial=question_data)替换answer_formset = AnswerFormSet(initial=question_data)的视图,我会得到'AnswerFormFormSet' object is not callable错误。我猜这是我应该编辑的路线?

回答

0

可以区分三种情况:

  1. 的选择是固定和总是相同的:添加choices kwarg与对向模型场的修复列表。这些选项将由ModelForm的相应字段自动使用。
  2. 的选择是在运行时生成的,但独立于特定的实例:

    一个)forms.Model[Multiple]ChoiceField:提供queryset kwarg与QuerySet这将在每次创建一个表单实例的时间进行评价。

    b)forms.ChoiceField:提供choices参数,它可以是在创建表单实例时调用的可调用参数。这必须返回类似于1的配对列表。

  3. 的选择是在运行时生成,它们依赖于形式的具体模型实例:

覆盖形式的__init__

class FooForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     super(FooForm, self).__init__(*args, **kwargs) 
     self.fields['bar_field'].choices = create_complex_choices(self.instance) 

如果你希望能够使用extra_information来调整这些选择,你只知道你的看法:

class FooForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     extra_info = kwargs.pop('extra_info', None) 
     super(FooForm, self).__init__(*args, **kwargs) 
     self.fields['bar_field'].choices = create_complex_choices(self.instance, extra_info) 
+0

根据我的理解,选项1和2不会起作用,因为答案选项与问题相关,并且至少有4个不同的选项集。它给我留下了选项3,我已经更新了这个问题。感谢您的帮助。 – GeeS