Django ModelForm: Wofür wird save (commit = False) verwendet?


86

Warum sollte ich jemals verwenden, save(commit=False)anstatt nur ein Formularobjekt aus der ModelFormUnterklasse zu erstellen und auszuführen?is_valid() , um sowohl das Formular als auch das Modell zu validieren?

Mit anderen Worten, wofür ist save(commit=False)?

Wenn es Ihnen nichts ausmacht, könnten Sie dann hypothetische Situationen angeben, in denen dies nützlich sein könnte?

Antworten:


106

Dies ist nützlich, wenn Sie die meisten Modelldaten aus einem Formular abrufen, aber einige ausfüllen müssen null=False Felder mit Nicht-Formulardaten füllen müssen.

Beim Speichern mit commit = False erhalten Sie ein Modellobjekt. Anschließend können Sie Ihre zusätzlichen Daten hinzufügen und speichern.

Dies ist ein gutes Beispiel für diese Situation.


Wenn Sie dann ein Modellobjekt erhalten, wie unterscheidet es sich dann von der Zuweisung eines zuvor instanziierten Objekts und der Zuweisung zur ModelForm? (dh form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

Benötigen Sie, commit=Falsewenn Sie Ihr Formular in einem CBVmit bearbeiten def form_valid? Können Sie nur form.instance.[field]zum Aktualisieren verwenden?
alias51

Gehen wir zu 100 :)
dani herrera

38

Hier ist die Antwort ( aus den Dokumenten ):

# Create a form instance with POST data.
>>> f = AuthorForm(request.POST)

# Create, but don't save the new author instance.
>>> new_author = f.save(commit=False)

Die häufigste Situation besteht darin, die Instanz aus dem Formular abzurufen, jedoch nur im Speicher, nicht in der Datenbank. Bevor Sie es speichern, möchten Sie einige Änderungen vornehmen:

# Modify the author in some way.
>>> new_author.some_field = 'some_value'

# Save the new instance.
>>> new_author.save()

1
Benötigen Sie, commit=Falsewenn Sie Ihr Formular in einem CBVmit bearbeiten def form_valid? Können Sie nur form.instance.[field]zum Aktualisieren verwenden?
alias51

14

Aus den Django-Dokumenten:

Diese save () -Methode akzeptiert ein optionales Commit-Schlüsselwortargument, das entweder True oder False akzeptiert. Wenn Sie save () mit commit = False aufrufen, wird ein Objekt zurückgegeben, das noch nicht in der Datenbank gespeichert wurde.

In diesem Fall liegt es an Ihnen, save () für die resultierende Modellinstanz aufzurufen. Dies ist nützlich, wenn Sie das Objekt vor dem Speichern benutzerdefiniert verarbeiten möchten oder wenn Sie eine der speziellen Optionen zum Speichern von Modellen verwenden möchten. Commit ist standardmäßig True.

Es scheint, dass save (commit = False) eine Modellinstanz erstellt, die an Sie zurückgegeben wird. Welches ist ordentlich für einige Nachbearbeitung, bevor es tatsächlich gespeichert wird!


10

Stellen Sie sich als "echtes Beispiel" ein Benutzermodell vor, bei dem die E-Mail-Adresse und der Benutzername immer identisch sind. Anschließend können Sie die Speichermethode Ihres ModelForm wie folgt überschreiben:

class UserForm(forms.ModelForm):
    ...
    def save(self):
        # Sets username to email before saving
        user = super(UserForm, self).save(commit=False)
        user.username = user.email
        user.save()
        return user

Wenn Sie commit=Falseden Benutzernamen nicht auf die E-Mail-Adresse festgelegt haben, müssen Sie entweder die Speichermethode des Benutzermodells ändern oder das Benutzerobjekt zweimal speichern (wodurch eine teure Datenbankoperation dupliziert wird).


Benötigen Sie, commit=Falsewenn Sie Ihr Formular in einem CBVmit bearbeiten def form_valid? Können Sie nur form.instance.[field]zum Aktualisieren verwenden?
alias51

1
            form = AddAttachmentForm(request.POST, request.FILES)
            if form.is_valid():
                attachment = form.save(commit=False)
                attachment.user = student
                attachment.attacher = self.request.user
                attachment.date_attached = timezone.now()
                attachment.competency = competency
                attachment.filename = request.FILES['attachment'].name
                if attachment.filename.lower().endswith(('.png','jpg','jpeg','.ai','.bmp','.gif','.ico','.psd','.svg','.tiff','.tif')):
                    attachment.file_type = "image"
                if attachment.filename.lower().endswith(('.mp4','.mov','.3g2','.avi','.flv','.h264','.m4v','.mpg','.mpeg','.wmv')):
                    attachment.file_type = "video"
                if attachment.filename.lower().endswith(('.aif','.cda','.mid','.midi','.mp3','.mpa','.ogg','.wav','.wma','.wpl')):
                    attachment.file_type = "audio"
                if attachment.filename.lower().endswith(('.csv','.dif','.ods','.xls','.tsv','.dat','.db','.xml','.xlsx','.xlr')):
                    attachment.file_type = "spreasheet"
                if attachment.filename.lower().endswith(('.doc','.pdf','.rtf','.txt')):
                    attachment.file_type = "text"
                attachment.save()

Hier ist mein Beispiel für die Verwendung von save (commit = False). Ich wollte überprüfen, welchen Dateityp ein Benutzer hochgeladen hat, bevor ich ihn in der Datenbank speichere. Ich wollte auch das Datum erhalten, an dem es angehängt war, da dieses Feld nicht im Formular war.


Dies ist ein Python-Code, den Sie nicht im Code-Snippet
ausführen können
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.