Django ModelForm: Lưu (cam kết = Sai) được sử dụng để làm gì?


88

Tại sao tôi lại sử dụng save(commit=False)thay vì chỉ tạo một đối tượng biểu mẫu từ ModelFormlớp con và chạy is_valid()để xác thực cả biểu mẫu và mô hình?

Nói cách khác, save(commit=False)để làm gì?

Nếu không phiền, các bạn có thể đưa ra các tình huống giả định mà điều này có thể hữu ích không?

Câu trả lời:


110

Điều đó hữu ích khi bạn lấy hầu hết dữ liệu mô hình của mình từ một biểu mẫu, nhưng cần điền một số null=Falsetrường có dữ liệu không phải biểu mẫu.

Lưu với cam kết = False giúp bạn có một đối tượng mô hình, sau đó bạn có thể thêm dữ liệu bổ sung của mình và lưu nó.

Đây là một ví dụ điển hình cho tình huống đó.


Nhưng sau đó nếu điều này giúp bạn trở thành một đối tượng mô hình, thì nó khác với việc gán một đối tượng được khởi tạo trước đó và gán nó cho ModelForm như thế nào? (tức là form = forms.SampleForm(instance = models.Sample))
OzzyTheGiant

Bạn có cần commit=Falsenếu bạn đang xử lý biểu mẫu của mình CBVvới def form_valid? Bạn có thể chỉ cần sử dụng form.instance.[field]để cập nhật?

Hãy đi đến 100 :)
dani herrera

39

Đây là câu trả lời ( từ tài liệu ):

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

Tình huống phổ biến nhất là lấy thể hiện từ biểu mẫu nhưng chỉ 'trong bộ nhớ', không phải trong cơ sở dữ liệu. Trước khi lưu nó, bạn muốn thực hiện một số thay đổi:

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

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

1
Bạn có cần commit=Falsenếu bạn đang xử lý biểu mẫu của mình CBVvới def form_valid? Bạn có thể chỉ cần sử dụng form.instance.[field]để cập nhật?

14

Từ tài liệu Django:

Phương thức save () này chấp nhận một đối số từ khóa cam kết tùy chọn, chấp nhận True hoặc False. Nếu bạn gọi save () với commit = False, thì nó sẽ trả về một đối tượng chưa được lưu vào cơ sở dữ liệu.

Trong trường hợp này, bạn có thể gọi save () trên phiên bản mô hình kết quả. Điều này hữu ích nếu bạn muốn thực hiện xử lý tùy chỉnh trên đối tượng trước khi lưu đối tượng hoặc nếu bạn muốn sử dụng một trong các tùy chọn lưu mô hình chuyên biệt. cam kết là Đúng theo mặc định.

Có vẻ như save (commit = False) tạo ra một thể hiện mô hình, nó sẽ trả về cho bạn. Điều này thật gọn gàng cho một số xử lý bài viết trước khi thực sự lưu nó!


10

Như một "ví dụ thực tế", hãy xem xét mô hình người dùng trong đó địa chỉ email và tên người dùng luôn giống nhau, sau đó bạn có thể ghi đè phương thức lưu của ModelForm như:

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

Nếu bạn không sử dụng commit=Falseđể đặt tên người dùng thành địa chỉ email, bạn phải sửa đổi phương pháp lưu của mô hình người dùng hoặc lưu đối tượng người dùng hai lần (điều này sao chép một thao tác cơ sở dữ liệu đắt tiền.)


Bạn có cần commit=Falsenếu bạn đang xử lý biểu mẫu của mình CBVvới def form_valid? Bạn có thể chỉ cần sử dụng form.instance.[field]để cập nhật?

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

đây là ví dụ của tôi về việc sử dụng save (commit = False). Tôi muốn kiểm tra loại tệp mà người dùng đã tải lên trước khi lưu vào cơ sở dữ liệu. Tôi cũng muốn lấy ngày nó được đính kèm vì trường đó không có trong biểu mẫu.


đây là một mã python bạn không thể chạy nó trong đoạn mã
Ayoub Benayache
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.