我有一個3級的測試模型,我想將其作爲嵌套表單集呈現。每個測試都有多個結果,每個結果可以有多個行。我下面Yergler's method創建嵌套表單集,與this SO question,更新Yergler對最近的Django的版本(我是1.4)在Django中保存嵌套表單的正確方法
我遇到了麻煩,因爲我想用表單集的「額外」參數包括代碼一起表單集中的額外行。每行的ForeignKey必須指向該行所屬的結果,但不能由用戶更改,因此我使用HiddenInput字段在每個FormSet的行中包含結果。
這導致了「丟失必填字段」驗證錯誤,因爲result
場總是充滿了(在add_fields,傳入三個),但text
和severity
不得(如果用戶選擇不進入另一條線)。我不知道處理這種情況的正確方法。我想認爲,我不需要在add_fields中包含初始的result
值,並且必須有一個更好的實際工作方式。下面
更新對這個問題
的底部,如果有必要,我會很樂意增加更多的細節。
我的自定義表單集的代碼:
LineFormSet = modelformset_factory(
Line,
form=LineForm,
formset=BaseLineFormSet,
extra=1)
class BaseResultFormSet(BaseInlineFormSet):
def __init__(self, *args, **kwargs):
super(BaseResultFormSet, self).__init__(*args, **kwargs)
def is_valid(self):
result = super(BaseResultFormSet, self).is_valid()
for form in self.forms:
if hasattr(form, 'nested'):
for n in form.nested:
n.data = form.data
if form.is_bound:
n.is_bound = True
for nform in n:
nform.data = form.data
if form.is_bound:
nform.is_bound = True
# make sure each nested formset is valid as well
result = result and n.is_valid()
return result
def save_all(self, commit=True):
objects = self.save(commit=False)
if commit:
for o in objects:
o.save()
if not commit:
self.save_m2m()
for form in set(self.initial_forms + self.saved_forms):
for nested in form.nested:
nested.save(commit=commit)
def add_fields(self, form, index):
# Call super's first
super(BaseResultFormSet, self).add_fields(form, index)
try:
instance = self.get_queryset()[index]
pk_value = instance.pk
except IndexError:
instance=None
pk_value = hash(form.prefix)
q = Line.objects.filter(result=pk_value)
form.nested = [
LineFormSet(
queryset = q, #data=self.data, instance = instance, prefix = 'LINES_%s' % pk_value)]
prefix = 'lines-%s' % pk_value,
initial = [
{'result': instance,}
]
)]
測試模型
class Test(models.Model):
id = models.AutoField(primary_key=True, blank=False, null=False)
attempt = models.ForeignKey(Attempt, blank=False, null=False)
alarm = models.ForeignKey(Alarm, blank=False, null=False)
trigger = models.CharField(max_length=64)
tested = models.BooleanField(blank=False, default=True)
合成模型
class Result(models.Model):
id = models.AutoField(primary_key=True)
test = models.ForeignKey(Test)
location = models.CharField(max_length=16, choices=locations)
was_audible = models.CharField('Audible?', max_length=8, choices=audible, default=None, blank=True)
線型號
class Line(models.Model):
id = models.AutoField(primary_key=True)
result = models.ForeignKey(Result, blank=False, null=False)
text = models.CharField(max_length=64)
severity = models.CharField(max_length=4, choices=severities, default=None)
更新
昨晚我已將此添加到我的LineForm(的ModelForm)類:
def save(self, commit=True):
saved_instance = None
if not(len(self.changed_data) == 1 and 'result' in self.changed_data):
saved_instance = super(LineForm, self).save(commit=commit)
return saved_instance
它忽略了要求保存,如果僅結果(一HiddenInput)填充出。我還沒有遇到任何問題,但我還沒有嘗試添加新的表單。
您能否詳細解釋一下該方法的工作原理?我已經包含一個必填字段作爲HiddenInput,這是我的問題的來源(這是我的第一個Django項目也沒有幫助) – JohnWoltman
我沒有仔細閱讀你的問題,它只是讓我想起了一些我我一直在做我自己的代碼。我修改了我的答案,希望更有幫助。 – Anentropic
從Django角度看,這是有道理的,但是通過從模型代碼中刪除「result」字段將意味着Django不再將結果保存到正確的表中了。我認爲。剛剛接觸Django,我不太確定。 – JohnWoltman