问题
I have a question related this one: How to handle the validation of the model form when the model has a clean method if the model form excluded some fields?
This is my model:
class StudentIelts(Model):
SCORE_CHOICES = [(float(i/2), float(i/2)) for i in range(0, 19)]
IELTS_TYPE_CHOICES = [('General', 'General'), ('Academic', 'Academic'), ]
student = OneToOneField(Student, on_delete=CASCADE)
has_ielts = BooleanField(default=False, )
ielts_listening = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_reading = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_writing = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_speaking = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_overall = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_exam_type = CharField(max_length=10, null=True, blank=True, choices=IELTS_TYPE_CHOICES, )
ielts_exam_date = DateField(null=True, blank=True, )
ielts_file = FileField(upload_to=student_directory_path, null=True, blank=True, )
student_ielts_non_empty_fields = \
{
'ielts_listening': 'please enter your listening score',
'ielts_reading': 'please enter your reading score',
'ielts_writing': 'please enter your writing score',
'ielts_speaking': 'please enter your speaking score',
'ielts_overall': 'please enter your overall score',
'ielts_exam_type': 'please enter your exam type',
'ielts_exam_date': 'please specify your exam date',
}
def clean(self):
errors = {}
if self.has_ielts:
for field_name, field_error in self.student_ielts_non_empty_fields.items():
if getattr(self, field_name) is None:
errors[field_name] = field_error
if errors:
raise ValidationError(errors)
class StudentIeltsFilterForm(ModelForm):
class Meta:
model = StudentIelts
fields = ['has_ielts', 'ielts_listening', 'ielts_reading', 'ielts_writing', 'ielts_speaking', 'ielts_overall', 'ielts_exam_type', ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.instance.student_ielts_non_empty_fields.pop('ielts_exam_date')
But when I check the has_ielts field and submit the form I see the error below:
Exception Type: KeyError
Exception Value: 'ielts_exam_date'
My view is as below:
def home(request):
template_name = 'programs/home.html'
home_context = {}
if request.POST:
return HttpResponse('We did not expect a POST request')
else:
if request.GET.get('hidden'):
student_ielts_filter_form = StudentIeltsFilterForm(request.GET)
if student_ielts_filter_form.is_valid():
querystring = urlencode(request.GET)
return redirect(reverse('programs') + '?' + querystring)
else:
student_ielts_filter_form = StudentIeltsFilterForm()
home_context.update({
'student_ielts_filter_form': student_ielts_filter_form,
})
return render(request, template_name, home_context)
回答1:
This is the answer given by @dirkgroten . I am documenting his answer:
class StudentIelts(Model):
SCORE_CHOICES = [(float(i/2), float(i/2)) for i in range(0, 19)]
IELTS_TYPE_CHOICES = [('General', 'General'), ('Academic', 'Academic'), ]
student = OneToOneField(Student, on_delete=CASCADE)
has_ielts = BooleanField(default=False, )
ielts_listening = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_reading = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_writing = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_speaking = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_overall = FloatField(choices=SCORE_CHOICES, null=True, blank=True, )
ielts_exam_type = CharField(max_length=10, null=True, blank=True, choices=IELTS_TYPE_CHOICES, )
ielts_exam_date = DateField(null=True, blank=True, )
ielts_file = FileField(upload_to=student_directory_path, null=True, blank=True, )
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.student_ielts_non_empty_fields = \
{
'ielts_listening': 'please enter your listening score',
'ielts_reading': 'please enter your reading score',
'ielts_writing': 'please enter your writing score',
'ielts_speaking': 'please enter your speaking score',
'ielts_overall': 'please enter your overall score',
'ielts_exam_type': 'please enter your exam type',
'ielts_exam_date': 'please specify your exam date',
}
def clean(self):
errors = {}
if self.has_ielts:
for field_name, field_error in self.student_ielts_non_empty_fields.items():
if getattr(self, field_name) is None:
errors[field_name] = field_error
if errors:
raise ValidationError(errors)
and
class StudentIeltsFilterForm(ModelForm):
class Meta:
model = StudentIelts
fields = ['has_ielts', 'ielts_listening', 'ielts_reading', 'ielts_writing', 'ielts_speaking', 'ielts_overall', 'ielts_exam_type', ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.instance.student_ielts_non_empty_fields.pop('ielts_exam_date')
read his explanation: How to handle the validation of the model form when the model has a clean method if the model form excluded some fields?
来源:https://stackoverflow.com/questions/58258213/how-to-remove-a-field-from-modelform-model-instance