1

我有一个问题模型和一个选择模型。一个选择可以是正确的,也可以是不正确的。

class Choice(models.Model):
    question = models.ForeignKey('Question', related_name='choices')
    choice = models.CharField(max_length=255)
    is_correct = models.BooleanField(default=False)
    times_chosen = models.IntegerField(editable=False, default=0)

    def __unicode__(self):
        return self.choice + ' / ' + str(self.times_chosen)


#multiple choice question
class Question(models.Model):

    def _get_average(self):
        "Returns the average in percent"
        if self.times_total == 0:
            return 0.0
        return (self.times_correct / float(self.times_total)) * 100

    def _get_answer(self):
        "Returns the answer"

        for choice in self.choices.all():
            if choice.question == self and choice.is_correct:
                return choice.choice
        return None

    def __unicode__(self):
        return self.question

    question = models.CharField(max_length=255)
    modules = models.ManyToManyField(Module, related_name='questions')

    creator = models.CharField(max_length=255)
    last_updated = models.DateTimeField(auto_now=True)

    #used for global statistics per question
    times_correct = models.IntegerField(editable=False, default=0)
    times_total = models.IntegerField(editable=False, default=0)

    #Derived values
    average = property(_get_average)
    answer = property(_get_answer)

首先,我尝试仅在有答案时保存。

def save(self):
    " Make sure that a question has at least one answer "
    if self._get_answer():
        super(Question, self).save()

但是问题无法保存,因为它没有答案集,并且在保存之前不能有答案集。

所以我想每当我有一个问题表格时,我都需要在它有效之前检查它是否有答案。

该表单在管理员中,它使用内联。所以我创建了一个新的表单类,并想在管理员中使用它。

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 4

#TODO: move?
class QuestionAdminForm(forms.ModelForm):
    class Meta:
        model = Question


    def clean(self):
        data = self.cleaned_data
        logger.info(data)
        data = self.cleaned_data['choices']
        logger.info(data)
        #if "fred@example.com" not in data:
        #    raise forms.ValidationError("You have forgotten about Fred!")

        # Always return the cleaned data, whether you have changed it or
        # not.
        return data


class QuestionAdmin(admin.ModelAdmin):

    readonly_fields = ('average', 'last_updated')
    #list_display = ["question", "module", "average", "quiz"]
    #can't have below because M2M question-> module
    #list_display = ["question", "module", "average"]
    list_display = ["question", "average"]
    list_display_links = ["question"]
    list_filter = ['modules__name']
    search_fields = ["question", "modules__name", "quiz__name"]
    inlines = [ChoiceInline]
    actions = [duplicate_questions]
    form = QuestionAdminForm

但是 self.cleaned_data 不包含选择。所以我不能用它来验证其中一个是否是答案。

编辑

这是POST数据

creator 
u'Siecje'
choices-0-is_correct    
u'on'
choices-1-choice    
u'No'
choices-0-id    
u''
choices-__prefix__-question 
u''
choices-1-id    
u''
question    
u'Question Four?'
choices-0-question  
u''
csrfmiddlewaretoken 
u'hfRAW8B03as6XN5GpIygJ642VKMN2TPa'
choices-__prefix__-id   
u''
choices-3-id    
u''
_save   
u'Save'
choices-2-question  
u''
choices-2-id    
u''
choices-MAX_NUM_FORMS   
u'1000'
choices-INITIAL_FORMS   
u'0'
choices-3-question  
u''
choices-3-choice    
u'So'
choices-0-choice    
u'Yes'
choices-__prefix__-choice   
u''
choices-1-question  
u''
modules 
u'24'
choices-2-choice    
u'Maybe'
choices-TOTAL_FORMS 
u'4'
4

1 回答 1

0

这就是我最终基于Django 管理验证对内联表单所做的事情,该验证依赖于所有表单之间的字段总数

class CombinedFormSet(BaseInlineFormSet):
    # Validate formset data here
    def clean(self):
        super(CombinedFormSet, self).clean()
        for form in self.forms:
            if not hasattr(form, 'cleaned_data'):
                continue

            data = self.cleaned_data
            valid = False
            for i in data:
                if i != {}:
                    if i['is_correct']:
                        valid = True

            if not valid:
                #TODO: translate admin?
                raise forms.ValidationError("A Question must have an answer.")

            # Always return the cleaned data, whether you have changed it or
            # not.
            return data


class ChoiceInline(admin.TabularInline):
    model = Choice
    extra = 4
    formset = CombinedFormSet
于 2013-05-24T17:59:02.057 回答