我问了一个问题,我已经读了一点,现在我可以更好地表达我的需求了: How to do model level custom field validation in django?
我有这个模型:
class StudentIelts(Model):
SCORE_CHOICES = [(i/2, i/2) for i in range(0, 19)]
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, )
并具有以下模型形式:
class StudentIeltsForm(ModelForm):
class Meta:
model = StudentIelts
exclude = ('student')
def clean(self):
cleaned_data = super().clean()
has_ielts = cleaned_data.get("has_ielts")
if has_ielts:
msg = "Please enter your score."
for field in self.fields:
if not self.cleaned_data.get(str(field)):
self.add_error(str(field), msg)
else:
for field in self.fields:
self.cleaned_data[str(field)] = None
self.cleaned_data['has_ielts'] = False
return cleaned_data
我在这里所做的是检查has_ielts
是否为True
,然后应填写所有其他字段。如果has_ielts
为True
,甚至没有填写一个字段,我都会收到错误消息。如果has_ielts
为False
,则应保存一个带有has_ielts=False
和所有其他字段Null
的对象。我现在想在模型级别执行此操作:
class StudentIelts(Model):
SCORE_CHOICES = [(i/2, i/2) for i in range(0, 19)]
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, )
def clean(self):
# I do not know what to write in here
并具有以下模型形式:
class StudentIeltsForm(ModelForm):
class Meta:
model = StudentIelts
exclude = ('student')
在我的模型的clean方法中,我想要具有此逻辑的东西(这是psedue代码):
def clean(self):
msg = "Please enter your score."
if self.has_ielts:
my_dic = {}
for f in model_fields:
if f is None:
my_dic.update{str(field_name): msg}
raise ValidationError(my_dic)
我该怎么做?
如何在模型级别上获得与模型形式相同的结果?
答案 0 :(得分:1)
您需要显式声明应为非空的字段,否则您将循环浏览与清理方法无关的字段,例如id
和student
。有人可能想在以后添加一个非必填字段,并想知道为什么会引起验证错误。
class StudentIelts(Model):
# fields
non_empty_fields = ['ielts_reading', ...]
def clean(self):
errors = {}
if self.has_ielts:
for field_name in self.non_empty_fields:
if not getattr(self, field_name):
errors[field_name] = msg
if errors:
raise ValidationError(errors)