[Django]-Overriding the save method in Django ModelForm

169👍

In your save you have to have the argument commit. If anything overrides your form, or wants to modify what it’s saving, it will do save(commit=False), modify the output, and then save it itself.

Also, your ModelForm should return the model it’s saving. Usually a ModelForm’s save will look something like:

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

Read up on the save method.

Finally, a lot of this ModelForm won’t work just because of the way you are accessing things. Instead of self.callResult, you need to use self.fields['callResult'].

UPDATE: In response to your answer:

Aside: Why not just use ManyToManyFields in the Model so you don’t have to do this? Seems like you’re storing redundant data and making more work for yourself (and me :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

This allows for inheritance of CallResultTypeForm, just in case that’s ever necessary.

👤tghw

Leave a comment