60 votes

Remplacement de la méthode de sauvegarde dans Django ModelForm

Je vais avoir de la difficulté à justifier une dérogation ModelForm méthode de sauvegarde. C'est l'erreur que je reçois:

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

Mes intentions sont de disposer d'un formulaire de soumission de nombreuses valeurs pour les 3 zones, pour ensuite créer un objet pour chaque combinaison de ces champs, et pour enregistrer chacun de ces objets. Utile coup de pouce dans la bonne direction serait ace.

Fichier 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)

Fichier 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

Fichier admin.py

class CallResultTypeAdmin(admin.ModelAdmin):
    form = CallResultTypeForm

142voto

tghw Points 14244

Dans votre save vous devez avoir de l'argument commit. Si quoi que ce soit remplace votre forme, ou s'il veut modifier ce que c'est l'épargne, il n' save(commit=False), modifier la sortie, puis l'enregistrer lui-même.

Aussi, votre ModelForm devrait revenir au modèle de l'économie. Habituellement, un ModelForm de l' save ressemblera à quelque chose comme:

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

Lire sur l' save méthode.

Enfin, beaucoup de ces ModelForm ne fonctionne pas tout simplement parce que de la façon dont vous accédez à des choses. Au lieu de self.callResult, vous devez utiliser self.fields['callResult'].

Mise à JOUR: En réponse à votre réponse:

Aparté: Pourquoi ne pas utiliser ManyToManyFields dans le Modèle, de sorte que vous n'avez pas à faire cela? Semble que vous êtes un stockage redondant des données et de faire plus de travail pour vous-même (et à moi - :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, force_insert=False, force_update=False, *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

Cela permet à l'héritage de l' CallResultTypeForm, juste au cas où que jamais nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X