webentwicklung-frage-antwort-db.com.de

Überschreiben der Speichermethode in Django ModelForm

Ich habe Probleme, eine Speichermethode von ModelForm zu überschreiben. Dies ist der Fehler, den ich erhalte:

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

Ich beabsichtige, in einem Formular viele Werte für drei Felder einzureichen, dann für jede Kombination dieser Felder ein Objekt zu erstellen und jedes dieser Objekte zu speichern. Hilfreiche Stupser in die richtige Richtung wären Ass.

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

Datei 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

Datei admin.py

class CallResultTypeAdmin(admin.ModelAdmin):
    form = CallResultTypeForm
58
Josh Smeaton

In Ihrem save muss das Argument commit stehen. Wenn etwas Ihr Formular überschreibt oder ändern möchte, was gespeichert wird, wird save(commit=False) ausgeführt, die Ausgabe geändert und dann selbst gespeichert.

Außerdem sollte Ihre ModelForm das Modell zurückgeben, das sie speichert. Normalerweise sieht das save einer ModelForm ungefähr so ​​aus:

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

Lesen Sie weiter die save Methode .

Letztendlich wird ein Großteil dieser ModelForm nicht funktionieren, nur weil Sie auf bestimmte Dinge zugreifen. Anstelle von self.callResult Müssen Sie self.fields['callResult'] Verwenden.

[~ # ~] Update [~ # ~] : Als Antwort auf Ihre Antwort:

Nebenbei: Warum nicht einfach ManyToManyFields im Modell verwenden, damit Sie dies nicht tun müssen? Scheint, als würden Sie redundante Daten speichern und mehr Arbeit für sich selbst (und mich :P) Erledigen.

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

Dies ermöglicht die Vererbung von CallResultTypeForm, für den Fall, dass dies jemals notwendig ist.

138
tghw