数据录入人员不断添加和复制模型,因为他们无法轻松搜索内联现有项目,因此我在Brand ModelForm中添加了字段以允许自动提取品牌模型。
Brand.name是Brand模型的必填字段。因此,当仅填充自动填充字段时(在将现有品牌重新分配给当前公司的情况下),form.save()失败(其为空,但save()需要Brand.name,并且无论如何我都不知道我想将表单保存为模型实例,因为我刚刚重新分配了)。
如果在重新分配字段中提交了品牌,我想将Brands.company设置为父formset值,并在不尝试保存ModelForm的情况下静默返回。
关系是从品牌模型到公司模型的外键 - 公司可能有很多品牌。
一张图片说了千言万语......
class BrandAdminForm(forms.ModelForm):
reassign_existing = AutoCompleteSelectField('brand', required=False,)
confirm_reassign = BooleanField(required=False, help_text=_("Are you sure you want to reassign the brand?"))
def __init__(self, *args, **kwargs):
super(BrandAdminForm, self).__init__(*args, **kwargs)
self.fields['name'].required = False
def clean(self):
cleaned_data = super(BrandAdminForm, self).clean()
import ipdb; ipdb.set_trace()
if cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and not self.instance.pk:
self.instance = cleaned_data['reassign_existing']
cleaned_data['reassign_existing'].company = self.instance.company
cleaned_data['id'] = self.instance.id
cleaned_data['category'] = self.instance.category.all()
cleaned_data['website'] = self.instance.website
cleaned_data['twitter_handle'] = self.instance.twitter_handle
cleaned_data['wikipedia_uri'] = self.instance.wikipedia_uri
cleaned_data['email'] = self.instance.email
cleaned_data['name'] = self.instance.name
return cleaned_data
elif cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and self.instance.pk:
raise forms.ValidationError("You can't reassign AND add/edit a brand in the same form. Clear one of the sections.")
else:
if not cleaned_data['name']:
msg = u"You must add a name to a new brand."
self._errors["name"] = self.error_class([msg])
return cleaned_data
class Meta:
model = Brand
这种方法几乎可行,只有在重新分配品牌的类别时才会列出。这是M2M领域。
当'reassign_existing'中有值但最终以
结尾时,我试图将保存重写为不保存'NoneType' object has no attribute 'company_id'
这是设置
class BrandAdminForm(forms.ModelForm):
reassign_existing = AutoCompleteSelectField('brand', required=False,
)
confirm_reassign = BooleanField(required=False, help_text=_("Are you sure you want to reassign the brand?"))
def __init__(self, *args, **kwargs):
super(BrandAdminForm, self).__init__(*args, **kwargs)
self.fields['name'].required = False
def clean(self):
cleaned_data = super(BrandAdminForm, self).clean()
if cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and not self.instance.pk:
cleaned_data['reassign_existing'].company = self.instance.company
cleaned_data['reassign_existing'].save()
return cleaned_data
elif cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and self.instance.pk:
raise forms.ValidationError("You can't reassign AND add/edit a brand in the same form. Clear one of the sections.")
else:
if not cleaned_data['name']:
msg = u"You must add a name to a new brand."
self._errors["name"] = self.error_class([msg])
return cleaned_data
def save(self, *args, **kwargs):
if not self.cleaned_data['reassign_existing']:
super(BrandAdminForm, self).save(*args, **kwargs)
class Meta:
model = Brand
答案 0 :(得分:1)
这是我提出的解决方案。需要继承ModelForm和BaseFormsetInline
class BrandBaseFormSet(BaseInlineFormSet):
def save_new(self, form, commit=True):
import ipdb;ipdb.set_trace()
if form.cleaned_data['reassign_existing'] \
and form.cleaned_data['confirm_reassign'] \
and not form.instance.pk:
return form.cleaned_data['reassign_existing']
else:
import ipdb;ipdb.set_trace()
return super(BrandBaseFormSet, self).save_new(form, commit=commit)
class BrandAdminForm(forms.ModelForm):
"""
Allow for reassigning of reverse fk relationships inline of the child.
"""
reassign_existing = AutoCompleteSelectField('brand', required=False)
confirm_reassign = BooleanField(required=False)
def __init__(self, *args, **kwargs):
super(BrandAdminForm, self).__init__(*args, **kwargs)
self.fields['name'].required = False
def clean(self):
"""
Here we check if its a new form or reassigning an existing brand. If its reassigning, we just do that in
this method.
:return: cleaned form data
"""
cleaned_data = super(BrandAdminForm, self).clean()
if cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and not self.instance.pk:
cleaned_data['reassign_existing'].company = self.instance.company
cleaned_data['reassign_existing'].save()
return cleaned_data
elif cleaned_data['reassign_existing'] \
and cleaned_data['confirm_reassign'] \
and self.instance.pk:
raise forms.ValidationError("You can't reassign AND add/edit a brand in the same form. Clear one of the sections.")
else:
if not cleaned_data['name']:
msg = u"You must add a name to a new brand."
self._errors["name"] = self.error_class([msg])
return cleaned_data
def save(self, *args, **kwargs):
if not self.cleaned_data['reassign_existing']:
return super(BrandAdminForm, self).save(*args, **kwargs)
else:
return self.cleaned_data['reassign_existing']
class Meta:
model = Brand