我有两个通过ForeignKey连接在一起的对象。
class Question(models.Model):
text = models.Charfield()
class AnswerOption(models.Model):
text = models.Charfield()
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="options")
当在管理界面中创建Question
时,我为AnswerOptions
使用了一个内联表单,以便同时创建它们。我想在Question
上执行一些验证,它需要访问新的AnswerOptions
才能做出决定。
我已经向clean
添加了一个Question
方法,但是options
属性是空的。
验证Question
的正确方法是什么?
编辑清楚地表明,Question
需要访问AnswerOptions
才能验证所有内容。
编辑添加了对在管理界面中使用InlineForm for AnswerOptions
的显式引用。
发布于 2019-12-19 05:58:19
这就是我发现的:
在管理接口中创建内联表单时,Django创建一个Formset
来处理多个表单。(示例这里与我的用例相同)
Formsets
和其他窗体一样有一个clean()
方法,它们有一个forms
属性来访问子窗体。就像普通表单一样,它们有一个instance
属性,该属性引用“基类”,而单个表单具有一个instance
属性,它为您提供新提交的数据的一个实例。
把这一切结合在一起:
# models.py
class Question(models.Model):
text = models.Charfield()
class AnswerOption(models.Model):
text = models.Charfield()
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="options")
# admin.py
from django.contrib import admin
from django.forms.models import BaseInlineFormSet
class AnswerOptionFormset(BaseInlineFormset):
def clean(self):
super().clean() # See note in docs about calling this to check unique constraints
#self.instance -> Question, with all the newly submitted, and validated, data.
#self.forms -> iterator over all the submitted AnswerOption forms
#for f in self.forms:
# f.instance -> instance of AnswerOption containing the new validated data
#Note: self.instance.options will refer to the previous AnswerOptions
#raise ValidationError for anything that is wrong.
#It is also possible to modify the data in self.instance or form.instance instead.
class AnswerOptionInline(admin.TabularInline):
formset = AnswerOptionFormset # note formset on AnswerOption NOT QuestionAdmin
class QuestionAdmin(admin.ModelAdmin):
inlines = [AnswerOptionInline]
发布于 2019-12-17 13:30:04
我会通过Django表单来完成这个任务,它有一个更健壮的验证接口。表单上的clean
方法是进行这种类型验证的地方。
# forms.py
from django import forms
from .models import Question
class QuestionForm(forms.Form):
text = models.Charfield()
class Meta:
model = Question
def clean(self):
options = self.cleaned_data['options']
if not option.are_ok:
raise forms.ValidationError
# admin.py
from django import admin
from .forms import QuestionForm
class QuestionAdmin(admin.ModelAdmin):
form = QuestionForm
...
来自医生们:
表单子类的clean()方法可以执行需要访问多个表单字段的验证。这是您可能会进行检查的地方,例如“如果字段A被提供,字段B必须包含一个有效的电子邮件地址”。如果愿意,此方法可以返回一个完全不同的字典,该字典将用作cleaned_data。
https://stackoverflow.com/questions/59378296
复制相似问题