Django ModelForm: Kaydetme (commit = False) ne için kullanılır?


90

Neden hiç kullanayım save(commit=False)ModelForm alt sınıftan bir form nesnesi is_valid()oluşturmak ve hem formu hem de modeli doğrulamak için çalıştırmak yerine kullanayım?

Başka bir deyişle, ne save(commit=False)için?

Sakıncası yoksa, bunun yararlı olabileceği varsayımsal durumlar sağlayabilir misiniz?

Yanıtlar:


111

Bu, model verilerinizin çoğunu bir formdan aldığınızda yararlıdır, ancak bazı null=Falsealanları form dışı verilerle doldurmanız gerekir .

Commit = False ile kaydetme size bir model nesnesi verir, daha sonra ekstra verilerinizi ekleyebilir ve kaydedebilirsiniz.

Bu, bu duruma güzel bir örnek.


Ama bu size bir model nesnesi getirirse, daha önce somutlaştırılmış bir nesneyi atamaktan ve onu ModelForm'a atamaktan farkı nedir? (ie form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

commit=FalseFormunuzu bir CBVile işliyorsanız ihtiyacınız var def form_validmı? Sadece form.instance.[field]güncellemek için kullanabilir misin ?
rumuz51

Hadi 100'e gidelim :)
dani herrera

43

İşte cevap ( dokümanlardan ):

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

En yaygın durum, örneği formdan almaktır, ancak veritabanında değil yalnızca 'bellekte' almaktır. Kaydetmeden önce bazı değişiklikler yapmak istiyorsunuz:

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

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

1
commit=FalseFormunuzu bir CBVile işliyorsanız ihtiyacınız var def form_validmı? Sadece form.instance.[field]güncellemek için kullanabilir misin ?
rumuz51

15

Django belgelerinden:

Bu save () yöntemi, True veya False kabul eden isteğe bağlı bir commit anahtar kelime bağımsız değişkenini kabul eder. Save () işlevini commit = False ile çağırırsanız, veritabanına henüz kaydedilmemiş bir nesne döndürür.

Bu durumda, ortaya çıkan model örneğinde save () 'i çağırmak size kalmıştır. Bu, nesneyi kaydetmeden önce özel işlem yapmak istiyorsanız veya özelleştirilmiş model kaydetme seçeneklerinden birini kullanmak istiyorsanız kullanışlıdır. commit varsayılan olarak True'dur.

Görünüşe göre save (commit = False) size geri döndüğü bir model örneği yaratıyor. Aslında kaydetmeden önce bazı sonradan işlemler için düzgün olan!


10

"Gerçek bir örnek" olarak, e-posta adresinin ve kullanıcı adının her zaman aynı olduğu bir kullanıcı modeli düşünün ve ardından ModelForm'unuzun kaydetme yönteminin üzerine aşağıdaki gibi yazabilirsiniz:

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

commit=FalseKullanıcı adını e-posta adresine ayarlamak için kullanmadıysanız , kullanıcı modelinin kaydetme yöntemini değiştirmeniz veya kullanıcı nesnesini iki kez kaydetmeniz gerekir (bu da pahalı bir veritabanı işlemini kopyalar.)


commit=FalseFormunuzu bir CBVile işliyorsanız ihtiyacınız var def form_validmı? Sadece form.instance.[field]güncellemek için kullanabilir misin ?
rumuz51

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

İşte kaydetme (commit = False) kullanma örneğim. Veritabanına kaydetmeden önce bir kullanıcının ne tür bir dosya yüklediğini kontrol etmek istedim. Ayrıca formda o alan olmadığı için eklendiği tarihi de almak istedim.


bu bir python kodudur, kod pasajında ​​çalıştıramazsınız
Ayoub Benayache

0

Basit bir deyişle, burada form nesnesini güncelliyoruz ve değerleri şu anda veritabanına kaydetmediklerini bildiriyoruz, örnekle bazı girdileri değiştirebiliriz ve ardından tüm değerleri veritabanına kaydetmek için .save () kullanabiliriz.

Bu bize tüm değerleri HTML formundan alma ve gereksinimlerimize göre özelleştirme ve ardından örneği kaydetme esnekliği sağlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.