Django ModelForm: для чого використовується save (commit = False)?


88

Чому я коли-небудь використовував би save(commit=False)замість того, щоб просто створювати об’єкт форми з ModelFormпідкласу та запускати is_valid()для перевірки форми та моделі?

Іншими словами, для чого save(commit=False)?

Якщо ви не проти, чи можете ви, хлопці, навести гіпотетичні ситуації, коли це може бути корисним?

Відповіді:


110

Це корисно, коли ви отримуєте більшу частину даних моделі з форми, але потрібно заповнити деякі null=Falseполя неформатними даними.

Збереження за допомогою commit = False дає вам об’єкт моделі, тоді ви можете додати додаткові дані та зберегти їх.

Це хороший приклад такої ситуації.


Але тоді, якщо це дає вам об’єкт моделі, чим він відрізняється від присвоєння раніше створеного об’єкта та присвоєння його ModelForm? (тобто form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

Вам необхідно , commit=Falseякщо ви обробляєте свою форму в CBVс def form_valid? Чи можете ви просто використовувати form.instance.[field]оновлення?
alias51

Підемо до 100 :)
dani herrera

39

Ось відповідь ( із документів ):

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

Найпоширеніша ситуація - отримати екземпляр із форми, але лише "в пам'яті", а не в базі даних. Перш ніж зберегти його, ви хочете внести деякі зміни:

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

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

1
Вам необхідно , commit=Falseякщо ви обробляєте свою форму в CBVс def form_valid? Чи можете ви просто використовувати form.instance.[field]оновлення?
alias51

14

З документів Django:

Цей метод save () приймає необов’язковий аргумент ключового слова коміту, який приймає True або False. Якщо ви викликаєте save () з комітом = False, тоді він поверне об'єкт, який ще не був збережений у базі даних.

У цьому випадку вам залишається зателефонувати save () у отриманому екземплярі моделі. Це корисно, якщо ви хочете виконати спеціальну обробку об’єкта перед його збереженням або якщо ви хочете скористатися одним із спеціалізованих варіантів збереження моделі. commit за замовчуванням має значення True.

Здається, save (commit = False) створює екземпляр моделі, який він повертає вам. Що є акуратним для певної обробки до того, як насправді зберегти її!


10

Як "реальний приклад" розглянемо модель користувача, де адреса електронної пошти та ім'я користувача завжди однакові, і тоді ви можете переписати метод збереження вашого ModelForm, наприклад:

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=Falseдля встановлення імені користувача на адресу електронної пошти, вам доведеться або змінити метод збереження моделі користувача, або двічі зберегти об'єкт користувача (що дублює дорогу операцію з базою даних).


Вам необхідно , commit=Falseякщо ви обробляєте свою форму в CBVс def form_valid? Чи можете ви просто використовувати form.instance.[field]оновлення?
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()

ось мій приклад використання save (commit = False). Я хотів перевірити, який тип файлу завантажив користувач, перш ніж зберігати його в базі даних. Я також хотів отримати дату, яку він додав, оскільки це поле не було у формі.


це код python, ви не можете його запустити у фрагменті коду
Ayoub Benayache
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.