重写 Django ModelForm 中的 save 方法

我在覆盖 ModelForm保存方法时遇到了麻烦。我收到的错误是:

Exception Type:     TypeError
Exception Value:    save() got an unexpected keyword argument 'commit'

我的意图是让一个表单提交3个字段的多个值,然后为这些字段的每个组合创建一个对象,并保存这些对象中的每一个。在正确的方向上有帮助的推动将是王牌。

文件 models.py

class CallResultType(models.Model):
id = models.AutoField(db_column='icontact_result_code_type_id', primary_key=True)
callResult = models.ForeignKey('CallResult', db_column='icontact_result_code_id')
campaign = models.ForeignKey('Campaign', db_column='icampaign_id')
callType = models.ForeignKey('CallType', db_column='icall_type_id')
agent = models.BooleanField(db_column='bagent', default=True)
teamLeader = models.BooleanField(db_column='bTeamLeader', default=True)
active = models.BooleanField(db_column='bactive', default=True)

文件 forms.py

from django.forms import ModelForm, ModelMultipleChoiceField
from callresults.models import *


class CallResultTypeForm(ModelForm):
callResult = ModelMultipleChoiceField(queryset=CallResult.objects.all())
campaign = ModelMultipleChoiceField(queryset=Campaign.objects.all())
callType = ModelMultipleChoiceField(queryset=CallType.objects.all())


def save(self, force_insert=False, force_update=False):
for cr in self.callResult:
for c in self.campain:
for ct in self.callType:
m = CallResultType(self) # this line is probably wrong
m.callResult = cr
m.campaign = c
m.calltype = ct
m.save()


class Meta:
model = CallResultType

文件 admin.py

class CallResultTypeAdmin(admin.ModelAdmin):
form = CallResultTypeForm
89323 次浏览

在你的 save中,你必须有参数 commit。如果有任何内容覆盖了表单,或者想要修改它正在保存的内容,它将执行 save(commit=False),修改输出,然后自己保存它。

另外,你的 ModelForm 应该返回它保存的模型。通常 ModelForm 的 save看起来像这样:

def save(self, commit=True):
m = super(CallResultTypeForm, self).save(commit=False)
# do custom stuff
if commit:
m.save()
return m

读读 save

最后,这个 ModelForm 的许多部分不能正常工作,这仅仅是因为您访问事物的方式。您需要使用 self.fields['callResult']而不是 self.callResult

更新 : 回应你的回答:

旁白: 为什么不在模型中使用 ManyToManyFields 呢?似乎你正在存储冗余数据,为自己(和我 :P)做更多的工作。

from django.db.models import AutoField
def copy_model_instance(obj):
"""
Create a copy of a model instance.
M2M relationships are currently not handled, i.e. they are not copied. (Fortunately, you don't have any in this case)
See also Django #4027. From http://blog.elsdoerfer.name/2008/09/09/making-a-copy-of-a-model-instance/
"""
initial = dict([(f.name, getattr(obj, f.name)) for f in obj._meta.fields if not isinstance(f, AutoField) and not f in obj._meta.parents.values()])
return obj.__class__(**initial)


class CallResultTypeForm(ModelForm):
callResult = ModelMultipleChoiceField(queryset=CallResult.objects.all())
campaign = ModelMultipleChoiceField(queryset=Campaign.objects.all())
callType = ModelMultipleChoiceField(queryset=CallType.objects.all())


def save(self, commit=True, *args, **kwargs):
m = super(CallResultTypeForm, self).save(commit=False, *args, **kwargs)
results = []
for cr in self.callResult:
for c in self.campain:
for ct in self.callType:
m_new = copy_model_instance(m)
m_new.callResult = cr
m_new.campaign = c
m_new.calltype = ct
if commit:
m_new.save()
results.append(m_new)
return results

这允许继承 CallResultTypeForm,以防万一。