我有一个问题模型和一个选择模型。选择是否正确。
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()
但问题无法保存,因为它没有应答集,并且在保存之前无法设置答案。
所以我想每当我有一个问题表格时,我需要在它有效之前检查它是否有答案。
表单位于admin中,它使用内联。所以我创建了一个新的表单类,并希望在管理员中使用它。
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'
答案 0 :(得分:0)
这是我最终根据Django admin validation for inline form which rely on the total of a field between all forms
做的事情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