2010-02-12 10 views

risposta

8

Non puoi fare inserzioni di massa decenti con get_or_create (o anche creare), e non c'è API per farlo facilmente.

Se la tua tabella è abbastanza semplice che creare righe con SQL raw non è troppo doloroso, non è troppo difficile; qualcosa di simile:

INSERT INTO site_entry (field1, field2) 
(
     SELECT i.field1, i.field2 
     FROM (VALUES %s) AS i(field1, field2) 
     LEFT JOIN site_entry as existing 
       ON (existing.field1 = i.field1 AND existing.field2 = i.field2) 
     WHERE existing.id IS NULL 
) 

dove% s è una stringa come ("field1, field2"), ("field3, field4"), ("field5, field6") che dovrete creare e fuggire correttamente da soli.

+0

Nel modo in cui l'ho fatto, puoi inserire in batch molte (centinaia) di righe in una singola query, che è come di solito vuoi Inserimenti batch –

+0

Sì, ma non riesco a farlo con MySQL. Sembra che non riesca a trovare la sintassi SQL corretta con la query proposta – kemar

+0

Informazioni su come ottenere un oggetto modello, in caso di esecuzione questa domanda? –

4

Dipende da ciò a cui si mira. È possibile utilizzare la funzione loaddata di manage.py per caricare i dati in un formato appropriato (JSON, XML, YAML, ...).

Vedere anche this discussion.

+2

questo è un collegamento interrotto ora gli articoli – wim

0

Direi che non c'è.

Ma mi chiedo che tipo sono i vostri item s, se hanno field1 e field2 come attributi. Sembra che esista un'altra classe che rappresenta una voce ma non è derivata da models.Model. Forse puoi omettere questa classe e creare immediatamente le istanze Entry invece di creare quegli elementi.

1

Se non sei sicuro che le cose nel tuo item_list esistano già nel tuo DB e hai bisogno degli oggetti del modello, allora get_or_create è sicuramente la strada da percorrere.

Se si conoscono le voci non sono nel vostro DB, si sarebbe molto meglio fare:

for item in item_list: 
    new = Entry.objects.create(
     field1 = item.field1, 
     field2 = item.field2, 
    ) 

E se non avete bisogno di oggetti, quindi basta ignorare il ritorno dalla chiamata di funzione. Non accelererà le cose di DB, ma aiuterà con la gestione della memoria se questo è un problema.

Se non si è certi che i dati siano già nel DB, ma su entrambi i campi è presente un flag unique=True, il DB imporrà l'univocità e sarà possibile rilevare l'eccezione e andare avanti. Ciò impedirà un ulteriore impatto del database evitando il tentativo di selezionare l'oggetto esistente.

from django.db import IntegrityError 

for item in item_list: 
    try: 
     new = Entry.objects.create(
      field1 = item.field1, 
      field2 = item.field2, 
     ) 
    except IntegrityError: 
     continue 

È possibile aumentare la velocità in entrambi i casi gestendo manualmente le transazioni. Django creerà e commetterà automaticamente una transazione per ogni salvataggio, ma fornisce alcuni decoratori che aumenteranno notevolmente l'efficienza se saprai che eseguirai molti salvataggi DB in una particolare funzione. I documenti di Django fanno un lavoro migliore per spiegare tutto questo di quanto posso qui, ma probabilmente vorresti prestare particolare attenzione a django.db.transaction.commit_on_success

+1

nel mio elenco_demand * * possono già esistere nel mio DB e sì, ho bisogno degli oggetti del modello. E nessuno dei campi ha un unico = Vero vincolo: '(Quindi penso che get_or_create sia la strada da percorrere: colpiamo il database! – kemar

+4

Questo non risponde alla domanda: in primo luogo, ha detto che voleva * bulk * inserire; "get_or_create è la strada da percorrere" non aiuta, dal momento che get_or_create non fa inserimenti di massa: inserire gli elementi uno alla volta è la cosa sbagliata da fare per l'inserimento di massa. Infine, non si possono solo causare errori e quindi ignorare in Postgresql finirai con errori di "transazione interrotta" a meno che tu non salti i checkpoint hoops –

1

Dal 1.4 si può fare bulk_create

Vedi the docs

* Non prestare attenzione agli avvertimenti anche se (più importante è che il metodo del modello save() non sarà chiamato, e quindi la pre_save e i segnali post_save non saranno inviati.) *

Problemi correlati