【问题标题】:Overriding the save method in Django ModelForm覆盖 Django ModelForm 中的保存方法
【发布时间】:2010-10-23 11:15:56
【问题描述】:

我无法覆盖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

【问题讨论】:

  • 澄清一下,您想为每个 callType、每个 callResult、每个活动保存一个 CallResultType?

标签: python django django-forms django-admin


【解决方案1】:

在您的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

阅读the save method

最后,由于您访问事物的方式,这个 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 的继承,以防万一。

【讨论】:

  • 我没有使用多对多字段,因为我需要映射表上的额外数据,所以无论如何我都需要通过一个表并在中间表上创建数据。
  • 我认为我无法在管理应用程序中创建我想要的行为。当我尝试查看对象时,会抛出错误,因为模型字段是外键,不是多对多关系。
  • 顺便说一句,您不应该忘记将*args**kwargs 参数添加到save 方法中。
  • 对于现在使用此功能的任何人(当前为 Django 1.10),ModelClass.save() method 现在只有 commit=True 参数——它没有 force_insertforce_update 参数。
猜你喜欢
  • 1970-01-01
  • 2016-07-26
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 2018-10-12
  • 2016-10-18
  • 1970-01-01
  • 2010-09-15
相关资源
最近更新 更多