Crea in blocco oggetti modello in django


90

Ho molti oggetti da salvare nel database, quindi voglio creare istanze del modello con quello.

Con django, posso creare tutte le istanze dei modelli, con MyModel(data), e poi voglio salvarle tutte.

Attualmente ho qualcosa del genere:

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

Mi chiedo se posso salvare direttamente un elenco di oggetti, ad esempio:

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

Come salvare tutti gli oggetti in una transazione?


Sembra che la palla stia rotolando sull'implementazione di una correzione per questo codice.djangoproject.com/ticket/19527
DanH

1
chiedendo list.save_all? Potresti quasi rispondere da solo parafrasando quella domanda e usando le prime 2 parole dalla tua domanda sull'argomento.
Sławomir Lenart

Risposte:


95

a partire dallo sviluppo di django, esiste bulk_createun metodo di gestione degli oggetti che prende come input un array di oggetti creati utilizzando il costruttore della classe. controlla django docs



1
Ma ricorda che bulk_create ha alcune limitazioni come non crea chiavi primarie se è un AutoField che save () fa automaticamente.
Hitesh Garg

@ HiteshGarg, è ancora vero oggi?
Raydel Miranda

1
@ RaydelMiranda, sì, è ancora vero. È proprio lì nella documentazione: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
Utilizzando Django 3.0.x confermo che l'utilizzo bulk_create()non innesca alcun segnale. Mi chiedo perché.
Enchance

42

Usa il bulk_create()metodo. Adesso è standard in Django.

Esempio:

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

1
Modificato in Django 1.10: è stato aggiunto il supporto per l'impostazione delle chiavi primarie sugli oggetti creati utilizzando bulk_create () quando si utilizza PostgreSQL.
argento elad

4

ha funzionato per me per utilizzare la gestione manuale delle transazioni per il ciclo (postgres 9.1):

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

infatti non è la stessa cosa dell'inserimento bulk del database 'nativo', ma permette di evitare / diminuire il trasporto / operazioni orms / query sql analizzare i costi


1
Questo è leggermente cambiato. Ora la transazione non ha commit_on_successpiù. Si dovrebbe usare transaction.atomic()See: stackoverflow.com/questions/21861207/...
t_io

4

Ecco come creare in blocco entità da file separati da colonne, lasciando da parte tutte le routine di annullamento quotazioni e di escape:

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

per un'implementazione a riga singola, puoi usare un'espressione lambda in una mappa

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

Qui, lambda abbina ogni elemento nell'elenco di elementi a x e crea un record di database se necessario.

Documentazione Lambda


Probabilmente vuoi menzionare che lambdadeve essere mapdistribuito items:map(lambda name: MyModel.objects.get_or_create(name = name), items)
Manoj Govindan

Sì, è un altro modo in cui provo a dire (:
FallenAngel

2

L'utilizzo di create causerà una query per ogni nuovo elemento. Se vuoi ridurre il numero di query INSERT, dovrai usare qualcos'altro.

Ho avuto un certo successo utilizzando lo snippet di inserimento in blocco, anche se lo snippet è piuttosto vecchio. Forse sono necessarie alcune modifiche per farlo funzionare di nuovo.

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


2

Dai un'occhiata a questo post del blog sul modulo bulkops .

Sulla mia app django 1.3, ho riscontrato un significativo aumento della velocità.


-19

Il modo più semplice è utilizzare il createmetodo Manager, che crea e salva l'oggetto in un unico passaggio.

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

+1. Se nameè unico e sono possibili input duplicati, sarebbe una buona idea utilizzarli get_or_create.
Manoj Govindan

16
Come risponde questo alla domanda? Model.objects.create è equivalente a object = MoModel (..) object.save (). E questo non lo fa in una transazione ...
automagic
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.