Tạo hàng loạt đối tượng mô hình trong django


90

Tôi có rất nhiều đối tượng để lưu trong cơ sở dữ liệu, và vì vậy tôi muốn tạo các phiên bản Model với nó.

Với django, tôi có thể tạo tất cả các phiên bản mô hình, với MyModel(data)và sau đó tôi muốn lưu tất cả chúng.

Hiện tại, tôi có một cái gì đó như thế:

for item in items:
    object = MyModel(name=item.name)
    object.save()

Tôi tự hỏi liệu tôi có thể lưu danh sách các đối tượng trực tiếp không, ví dụ:

objects = []
for item in items:
    objects.append(MyModel(name=item.name))
objects.save_all()

Làm thế nào để lưu tất cả các đối tượng trong một giao dịch?


Có vẻ như bóng đang lăn trên thực hiện một sửa chữa cho điều này code.djangoproject.com/ticket/19527
Danh

1
tự hỏi cho list.save_all? Bạn gần như có thể tự trả lời chỉ cần diễn giải câu hỏi đó và sử dụng 2 từ đầu tiên từ câu hỏi chủ đề của bạn.
Sławomir Lenart

Câu trả lời:


95

kể từ khi phát triển django, tồn tại bulk_createnhư một phương thức quản lý đối tượng lấy làm đầu vào là một mảng các đối tượng được tạo bằng cách sử dụng hàm tạo lớp. kiểm tra tài liệu django


12

1
Nhưng hãy nhớ Bulk_create có một số hạn chế như nó không tạo khóa chính nếu nó là AutoField mà save () tự động làm.
Hitesh Garg

@HiteshGarg, Ngày nay điều đó có còn đúng không?
Raydel Miranda

1
@RaydelMiranda, vâng, nó vẫn đúng. Nó ở ngay đó trong tài liệu:If the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does, unless the database backend supports it (currently only PostgreSQL).
interDist

1
Sử dụng Django 3.0.x và tôi xác nhận rằng việc sử dụng bulk_create()không kích hoạt bất kỳ tín hiệu nào. Tôi tự hỏi tại sao.
mê hoặc

42

Sử dụng bulk_create()phương pháp. Nó là tiêu chuẩn ở Django bây giờ.

Thí dụ:

Entry.objects.bulk_create([
    Entry(headline="Django 1.0 Released"),
    Entry(headline="Django 1.1 Announced"),
    Entry(headline="Breaking: Django is awesome")
])

1
Đã thay đổi trong Django 1.10: Hỗ trợ thiết lập khóa chính trên các đối tượng được tạo bằng cách sử dụng Bulk_create () khi sử dụng PostgreSQL đã được thêm vào.
elad silver

4

đã giúp tôi sử dụng xử lý giao dịch thủ công cho vòng lặp (postgres 9.1):

from django.db import transaction
with transaction.commit_on_success():
    for item in items:
        MyModel.objects.create(name=item.name)

trên thực tế, nó không giống như chèn hàng loạt cơ sở dữ liệu 'gốc', nhưng nó cho phép bạn tránh / descrease vận chuyển / hoạt động orms / truy vấn sql phân tích chi phí


1
Điều này hơi thay đổi. Bây giờ giao dịch không có commit_on_successnữa. Bạn nên sử dụng transaction.atomic()Xem: stackoverflow.com/questions/21861207/…
t_io 14/09/18

4

Dưới đây là cách tạo hàng loạt thực thể từ tệp được phân tách bằng cột, bỏ qua tất cả các quy trình hủy trích dẫn và hủy thoát:

SomeModel(Model):
    @classmethod
    def from_file(model, file_obj, headers, delimiter):
        model.objects.bulk_create([
            model(**dict(zip(headers, line.split(delimiter))))
            for line in file_obj],
            batch_size=None)

3

để triển khai một dòng, bạn có thể sử dụng biểu thức lambda trong bản đồ

map(lambda x:MyModel.objects.get_or_create(name=x), items)

Ở đây, lambda khớp từng mục trong danh sách mục thành x và tạo bản ghi Cơ sở dữ liệu nếu cần.

Tài liệu Lambda


Bạn có thể muốn đề cập đến việc lambdaphải mapkết thúc items:map(lambda name: MyModel.objects.get_or_create(name = name), items)
Manoj Govindan,

Ja, đó là một cách khác mà tôi cố gắng nói (:
FallenAngel

2

Sử dụng tạo sẽ tạo ra một truy vấn cho mỗi mục mới. Nếu bạn muốn giảm số lượng truy vấn CHÈN, bạn sẽ cần sử dụng một thứ khác.

Tôi đã thành công khi sử dụng đoạn mã Chèn hàng loạt, mặc dù đoạn mã này khá cũ. Có lẽ cần có một số thay đổi để nó hoạt động trở lại.

http://djangosnippets.org/snippets/446/


2

Kiểm tra bài viết trên blog này trên bulkops module.

Trên ứng dụng django 1.3 của tôi, tôi đã thấy tốc độ tăng đáng kể.


-19

Cách dễ nhất là sử dụng createphương thức Manager, phương thức này tạo và lưu đối tượng trong một bước duy nhất.

for item in items:
    MyModel.objects.create(name=item.name)

+1. Nếu nameđầu vào là duy nhất và trùng lặp là có thể thì bạn nên sử dụng get_or_create.
Manoj Govindan,

16
Làm thế nào để trả lời câu hỏi này? Model.objects.create tương đương với object = MoModel (..) object.save (). Và điều này không làm điều đó trong một giao dịch ...
automagic
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.