Django ModelForm: per cosa viene utilizzato save (commit = False)?


90

Perché dovrei mai usare save(commit=False)invece di creare semplicemente un oggetto modulo dalla ModelFormsottoclasse e correre is_valid()per convalidare sia il modulo che il modello?

In altre parole, a cosa serve save(commit=False)?

Se non vi dispiace, potreste fornire situazioni ipotetiche in cui questo potrebbe essere utile?

Risposte:


111

È utile quando si ottiene la maggior parte dei dati del modello da un modulo, ma è necessario popolare alcuni null=Falsecampi con dati non del modulo.

Salvando con commit = False ottieni un oggetto modello, quindi puoi aggiungere i tuoi dati extra e salvarli.

Questo è un buon esempio di quella situazione.


Ma poi se questo ti fa ottenere un oggetto modello, in che cosa differisce dall'assegnare un oggetto precedentemente istanziato e assegnarlo al ModelForm? (cioè form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

Hai bisogno commit=Falsese stai elaborando il tuo modulo in un CBVcon def form_valid? Puoi usare solo form.instance.[field]per aggiornare?
alias51

Andiamo a 100 :)
dani herrera

43

Ecco la risposta ( da documenti ):

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

La situazione più comune è ottenere l'istanza dal modulo ma solo "in memoria", non nel database. Prima di salvarlo vuoi apportare alcune modifiche:

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

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

1
Hai bisogno commit=Falsese stai elaborando il tuo modulo in un CBVcon def form_valid? Puoi usare solo form.instance.[field]per aggiornare?
alias51

15

Dai documenti di Django:

Questo metodo save () accetta un argomento di parola chiave commit opzionale, che accetta True o False. Se chiami save () con commit = False, restituirà un oggetto che non è stato ancora salvato nel database.

In questo caso, sta a te chiamare save () sull'istanza del modello risultante. Ciò è utile se si desidera eseguire un'elaborazione personalizzata sull'oggetto prima di salvarlo o se si desidera utilizzare una delle opzioni di salvataggio del modello specializzate. commit è True per impostazione predefinita.

Sembra che save (commit = False) crei un'istanza del modello, che ti restituisce. Che è perfetto per un po 'di post-elaborazione prima di salvarlo effettivamente!


10

Come "esempio reale", considera un modello utente in cui l'indirizzo e-mail e il nome utente sono sempre gli stessi, quindi potresti sovrascrivere il metodo di salvataggio del tuo ModelForm come:

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

Se non hai utilizzato commit=Falseper impostare il nome utente sull'indirizzo e-mail, dovresti modificare il metodo di salvataggio del modello utente o salvare due volte l'oggetto utente (il che duplica un'operazione costosa del database).


Hai bisogno commit=Falsese stai elaborando il tuo modulo in un CBVcon def form_valid? Puoi usare solo form.instance.[field]per aggiornare?
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()

ecco il mio esempio di utilizzo di save (commit = False). Volevo controllare quale tipo di file un utente ha caricato prima di salvarlo nel database. Volevo anche ottenere la data in cui era stata allegata poiché quel campo non era nel modulo.


questo è un codice Python che non puoi eseguire nello snippet di codice
Ayoub Benayache,

0

In parole semplici, qui aggiorniamo l'oggetto form e facciamo loro sapere che non salviamo i valori nel database in questo momento, potremmo modificare alcuni input con l'istanza e quindi utilizzare .save () per salvare tutti i valori nel database.

Questo ci dà la flessibilità di ottenere tutti i valori dal modulo HTML e personalizzarli in base alle nostre esigenze e quindi salvare l'istanza.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.