我想根据外键父模型的字段值设置选项。即"问题答案"模型外键"问题"设置为模型"问题"并且该模型包含一个字段" question_type"。如果" question_type" value为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)
更新
表单的初始化方法
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 = AnswerFormSet(initial=question_data)
替换为answer_formset = formset(initial=question_data)
,则会出现'AnswerFormFormSet' object is not callable
错误。我猜这是我应该编辑的那一行吗?
答案 0 :(得分:0)
您可以区分三种情况:
choices
kwarg与修复的对列表添加到模型字段中。这些选项将由ModelForm
的相应字段自动使用。选择是在运行时生成的,但与特定实例无关:
a)forms.Model[Multiple]ChoiceField
:向queryset
kwarg提供QuerySet
,每次创建表单实例时都会对其进行评估。
b)forms.ChoiceField
:提供choices
param,它可以是在创建表单实例时调用的可调用对象。这必须返回类似于1的对列表。
选择是在运行时生成的,和它们取决于表单的具体模型实例:
覆盖表单__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)