django复杂的formset问题

时间:2013-04-18 18:10:52

标签: python django python-2.7 django-forms

我有3个主要模型。问卷模型或问题集包含一组问题。所有用户响应都存储在答案中。

现在我必须生成一个formset,它将在问卷集中存储所有问题的答案。我怎么能在django做到这一点。到目前为止,我已经通过从给定的调查问卷中一次显示单个问题并存储响应来做到这一点。我的问题是基于问题类型使用两个不同的模型(MultipleChoiceAnswerForm,DescriptiveChoiceAnswerForm)并根据formtype验证它们。我如何在formset中使用它。

我是django的初学者,感谢任何帮助。

我的代码:

#Models.py

class Question(models.Model):
    statement = models.CharField(max_length=255)
    question_type = models.CharField(max_length=20, choices=get_qtypes())
    remarks = models.CharField(max_length=200, null=True, blank=True)

    def __unicode__(self):
        return '%s'%(self.statement)

class Questionnaire(models.Model):
    title = models.CharField(max_length=255)
    questionaire_type = models.CharField(max_length=20,choices=QUESTIONNAIRETYPE)
    context = models.ForeignKey(QuestionContext)
    questions = models.ManyToManyField(Question)

    timestamp = models.DateTimeField(auto_now=True)
    tathya_user = models.ForeignKey(User)

    def __unicode__(self):
        return '%s'%(self.title)

class Answer(models.Model):
    question = models.ForeignKey(Question)
    person = models.ForeignKey(Person)
    course = models.ForeignKey(Course)
    teacher=models.ForeignKey(Person, null=True, blank=True, default = None)
    questionaire = models.ForeignKey(Questionnaire)
    statement = models.CharField(max_length=255)


    def get_label(self):
        return '%s'%(self.question.statement)
    def get_choices(self):
        return get_questionchoices(self.question.question_type)

class DescriptiveAnswerForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(DescriptiveAnswerForm, self).__init__(*args, **kwargs)
        if kwargs.has_key('instance'):
            self.fields['statement'].label = kwargs['instance'].get_label()

    statement = forms.CharField(widget=forms.Textarea())
    class Meta:
        model = Answer
        exclude=('question','person','course','teacher','questionaire')

class MultipleChoiceAnswerForm(ModelForm):
    statement = forms.ChoiceField(widget=forms.RadioSelect(choices=EMPTY,attrs={'class': 'allradio',}))

    def __init__(self, *args, **kwargs):
        super(MultipleChoiceAnswerForm, self).__init__(*args, **kwargs)
        if kwargs.has_key('instance'):
            self.fields['statement'].label = kwargs['instance'].get_label()
            self.fields['statement'].choices = kwargs['instance'].get_choices()

    class Meta:
        model = Answer
        exclude=('question','person','course','teacher','questionaire')

###################################################################
#view.py
@login_required
def content_feedback_view_old(request,course_code):
    #do validation and other jobs
    questionnaire = get_questionnaire(some_params_like_coursecode)
    if request.method == 'POST':
        r_answer = Answer()
        r_answer.question = Question.objects.get(id=request.session['question'])
        r_answer.person = student
        r_answer.course = course
        r_answer.questionaire = questionnaire
        r_answer.tathya_user = User.objects.get(id=request.user.pk)
        rformtype = request.POST['formtype']
        if rformtype == 'MCQ':
            rform = MultipleChoiceAnswerForm(request.POST, instance=r_answer)
        else:
            rform = DescriptiveAnswerForm(request.POST, instance=r_answer)
        if rform.is_valid():
            rform.save()
        else:
           #return HttpResponse(printerror("Some problem occurred!"))
           errortext = "You need to provide an input!"

    questions = questionnaire.questions.all()
    allquestions = questions.count()
    tot_q = 0
    formtype = ""
    answered = 0
    for question in questions:
        try:
            answer=Answer.objects.get(question=question,person=student,course=course,questionaire=questionnaire)
            answered += 1
        except:
            answer = Answer()
            answer.question = question
            answer.person = student
            answer.course = course
            answer.questionaire = questionnaire
            answer.tathya_user = User.objects.get(id=request.user.pk)
            request.session['question']=question.id
            tot_q = tot_q + 1;
            if get_questiontype(question.question_type)=='MCQ':
                formtype="MCQ"
                form=MultipleChoiceAnswerForm(instance=answer)
            else:
                formtype="DESC"
                form=DescriptiveAnswerForm(instance=answer)
            break
    if tot_q>0:
        data_dict['FeedbackFormType']=formtype
        data_dict['FeedbackForm']=form
        data_dict['pagetitle']=context.description
        data_dict['coursecode']=course.course_code
        data_dict['feedbacktitle']="Content Feedback for "+course.fullname
        data_dict['Completeness'] = (answered/allquestions)*100
        data_dict['error']=errortext
    else:
        return HttpResponse(printerror("Thanks! You've answered all the questions!<br><a href=\"/feedback/teachers/"+course.course_code+"\">Continue with the teaching feedback.</a>"))
    req_context = RequestContext(request)
    return render_to_response('view.html', data_dict, req_context)

1 个答案:

答案 0 :(得分:1)

简单回答:只在单个AnswerForm上使用,让它管理它应该使用哪种字段和小部件,即:

class AnswerForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(AnswerForm, self).__init__(*args, **kwargs)
        instance = self.instance
        if instance.question.question_type == 'MCQ':
             self.fields["statement"] = forms.ChoiceField(
                 choices=instance.get_choices(),
                 widget=forms.RadioSelect(attrs={'class': 'allradio',})
                 )
        else:
             self.fields["statement"] = forms.CharField(
                widget=forms.Textarea()
                )
        self.fields['statement'].label = instance.get_label()

    class Meta:
        model = Answer
        exclude=('question','person','course','teacher','questionaire')

作为旁注,您可以将模型的属性值传递给模型的构造函数:

    answer = Answer(
        question=Question.objects.get(id=request.session['question']),
        person=student,
        course=course,
        questionnaire=questionnaire,
        # User.objects.get(id=request.user.pk) will return request.user
        # so it's just useless - just use request.user
        tathya_user=request.user
        )