Django'da toplu model nesneleri oluşturun


92

Veritabanına kaydedilecek çok sayıda nesnem var ve bu nedenle bununla Model örnekleri oluşturmak istiyorum.

Django ile tüm model örneklerini ile oluşturabilirim MyModel(data)ve sonra hepsini kaydetmek istiyorum.

Şu anda buna benzer bir şeyim var:

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

Bir nesne listesini doğrudan kaydedip kaydedemeyeceğimi merak ediyorum, örneğin:

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

Tüm nesneler tek bir işlemde nasıl kaydedilir?


Görünüşe göre top bu kod
DanH

1
list.save_all'ı mı merak ediyorsunuz? Neredeyse kendinize cevap verebilirsiniz, sadece merak ettiğiniz şeyi açıklayın ve konu sorunuzun ilk 2 kelimesini kullanın.
Sławomir Lenart

Yanıtlar:


99

django'nun geliştirilmesinden itibaren, bulk_createsınıf yapıcısı kullanılarak yaratılan nesnelerin bir dizisini girdi olarak alan bir nesne yöneticisi yöntemi vardır. django belgelerine göz atın



1
Ancak, bulk_create'in, save () işlevinin otomatik olarak yaptığı bir Otomatik Alan ise birincil anahtarlar oluşturmaması gibi bazı sınırlamaları olduğunu unutmayın.
Hitesh Garg

@HiteshGarg, bu günlerde hala doğru mu?
Raydel Miranda

1
@RaydelMiranda, evet yine de doğru. İşte dokümantasyonda: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
Kullanılması Django 3.0.x ve kullanıyorum onaylamak bulk_create()herhangi sinyalleri tetiklemez. Nedenini merak ediyorum.
ENCHANCE

43

bulk_create()Yöntem kullanın . Artık Django'da standart.

Misal:

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

1
Django 1.10'da değiştirildi: PostgreSQL kullanılarak bulk_create () kullanılarak oluşturulan nesnelerde birincil anahtarların ayarlanması desteği eklendi.
elad silver

4

döngü için manuel işlem işlemeyi kullanmam için çalıştı (postgres 9.1):

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

Aslında, 'yerel' veritabanı toplu ekleme ile aynı değildir, ancak taşıma / orms işlemleri / sql sorgu analiz maliyetlerinden kaçınmanıza / azaltmanıza olanak tanır


1
Bu biraz değişti. Artık işlem commit_on_successyok. Sen kullanmalıdır transaction.atomic(): Bkz stackoverflow.com/questions/21861207/...
t_io

4

Sütunla ayrılmış dosyadan varlıkları toplu olarak nasıl oluşturacağınız ve tüm alıntı yapmayan ve kaçmayan rutinleri bir kenara bırakarak şu şekilde:

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

tek satırlık bir uygulama için, bir haritada lambda ifadesi kullanabilirsiniz

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

Burada lambda, öğeler listesindeki her öğeyi x ile eşleştirir ve gerekirse bir Veritabanı kaydı oluşturur.

Lambda Belgeleri


Muhtemelen bahsetmek istiyorum lambdazorundadır mapüzerinde ped items:map(lambda name: MyModel.objects.get_or_create(name = name), items)
Manoj Govindan

Evet, söylemeye çalıştığım başka bir yol da bu (:
FallenAngel

2

Create'i kullanmak her yeni öğe için bir sorguya neden olur. INSERT sorgularının sayısını azaltmak istiyorsanız, başka bir şey kullanmanız gerekir.

Snippet oldukça eski olmasına rağmen, Toplu Ekleme pasajını kullanarak biraz başarılı oldum. Belki de tekrar çalışması için gerekli bazı değişiklikler vardır.

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



-20

En kolay yol, createnesneyi tek bir adımda oluşturan ve kaydeden Manager yöntemini kullanmaktır .

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

+1. Eğer nametektir ve yinelenen girişler mümkündür o zaman kullanmak iyi bir fikir olacaktır get_or_create.
Manoj Govindan

16
Bu soruya nasıl cevap veriyor? Model.objects.create, object = MoModel (..) object.save () ile eşdeğerdir. Ve bu tek bir işlemde yapmaz ...
automagic
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.