DJango如何为测验构建一个表单集?

时间:2011-03-24 18:15:22

标签: python django django-forms

我正在开展一个需要显示测验的测验应用程序 我的模型.py看起来像这样

from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin

#######################
#Quiz Structure Models#
#######################

class Quiz(models.Model):
    name = models.CharField(max_length = 255)
    creation = models.DateField(auto_now_add=True)
    creator = models.ForeignKey(User)

    def __unicode__ (self):
        return self.name

    def possible(self):
        total = 0
        for question in self.question_set.all():
            question.save()
            total += question.value
        return total



class Question(models.Model):
    question = models.CharField(max_length = 255)
    quiz = models.ForeignKey(Quiz)
    creator = models.ForeignKey(User)
    creation = models.DateField(auto_now_add = True)
    #objective = TODO: include standards linking in later versions
    value = models.IntegerField(default = 1)

    def __unicode__(self):
        return self.question

class Answer(models.Model):
    answer = models.CharField(max_length = 255)
    question = models.ForeignKey(Question)
    is_correct = models.BooleanField(default = False)
    #Creator is tied to the quiz


##########
#Attempts#
##########
class QuizAttempt(models.Model):
    student = models.ForeignKey(User)
    quiz = models.ForeignKey(Quiz)
    date = models.DateField(auto_now_add = True)
    #Score Method (similar to possible in Quiz 


class QuestionAttempt(models.Model):
    attempt = models.ForeignKey(QuizAttempt)
    question = models.ForeignKey(Question)
    response = models.ForeignKey(Answer)


#######
#Admin#
#######

class QuestionInline(admin.StackedInline):
    model = Question
    extra = 2


class AnswerInline(admin.StackedInline):
    model = Answer
    extra = 2


class QuizAdmin(admin.ModelAdmin):
    list_display = ('name', 'creator', 'creation', 'possible',)
    search_fields = ('name', 'creator')
    inlines = [QuestionInline]

admin.site.register(Quiz, QuizAdmin)

class QuestionAdmin(admin.ModelAdmin):
    inlines = [AnswerInline]
    search_fields = ('question', 'quiz', 'value',)
    list_display = ('question', 'quiz', 'value',)

admin.site.register(Question, QuestionAdmin)

我正在尝试构建一个表单或表单集,让我有一个包含所有问题的测验尝试的表单,所以它看起来像这样,并且让我回过头去看看保存学生尝试进行测验。

  1. 问题1
    • 选项a
    • ECT
  2. 到目前为止,看起来我最好的解决方案是使用这些模型构建一个formset,但我不确定如何指定我的选择以将其限制为与当前问题相关的答案,或者如何获得正确的formset在一个视图中。

2 个答案:

答案 0 :(得分:4)

如果我正确理解您的问题,您可能希望在执行时创建自定义Form,以及许多自定义Field。我期待的是:

class QuizForm(forms.Form):
    def __init__(self, data, questions, *args, **kwargs):
        self.questions = questions
        for question in questions:
            field_name = "question_%d" % question.pk
            choices = []
            for answer in question.answer_set().all():
                choices.append((answer.pk, answer.answer,))
            ## May need to pass some initial data, etc:
            field = forms.ChoiceField(label=question.question, required=True, 
                                      choices=choices, widget=forms.RadioSelect)
        return super(QuizForm, self).__init__(data, *args, **kwargs)
    def save(self):
        ## Loop back through the question/answer fields and manually
        ## update the Attempt instance before returning it.

可能需要额外调整才能通过管理界面完成这项工作,但这应该为您在执行时构建表单本身提供了良好的开端。

您的观点可能类似于:

# Assuming something like:  /quiz/69/ with "69" being the quiz PK.
def render_quiz(request, quiz_id):
    quiz = get_object_or_404(Quiz, quiz_id)
    form = QuizForm(questions=quiz.question_set.all())
    if request.method == "POST":
        form = QuizForm(request.POST, questions=quiz.question_set.all())
        if form.is_valid(): ## Will only ensure the option exists, not correctness.
            attempt = form.save()
            return redirect(attempt)
    return render_to_response('quiz.html', {"form": form})

答案 1 :(得分:1)

这是一个如何运作的粗略概念。

# define a form
class QuestionForm(forms.Form):
    id = forms.IntegerField(widget=forms.HiddenInput) # make it hidden- i know, not very elegant
    question = forms.CharField()
    answer = forms.CharField()

# views.py
def display(request):
    quiz = Quiz.objects.get(creator=request.user) # or some definition of quiz
    questions = quiz.question_set.all().values('id','question') # to get question text

    # define a formset
    QuestionFormSet = formset_factory(QuestionForm)
    # add initial data
    formset = QuestionFormSet(initial=questions)
    # should work because the field names are the same as that of form

    if request.method == 'POST':
        formset = QuestionFormSet(request.POST)
        if formset.is_valid():
            # associate answers here, note that you have access to the question id,
            # which is a hidden field in your form