2012-05-29 5 views
10

Stavo leggendo su Django bulk_create e alcuni dei suoi "difetti":Utilizzando Django bulk_create oggetti in chiavi esterne?

" 
This has a number of caveats though: 

1. The model's save() method will not be called, and the pre_save and post_save signals will not be sent. 
2. It does not work with child models in a multi-table inheritance scenario. 
3. If the model's primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does. 
" 

non ho capito appieno. Quindi, se ho un elenco di oggetti, passare in bulk_create:

objList = [a, b, c,] #none are saved 
model.objects.bulk_create(objList) 

Potrei continuare a utilizzare questi oggetti in chiavi esterne belle?

for obj in objList: 
    o = otherModel(something='asdfasdf', fkey=obj) 
    o.save() # will this be fine given the caveats stated above? 

Così sarà ok la relazione ForeignKey? Anche quando dice 2. Non funziona con modelli figlio in uno scenario di ereditarietà multi-tavolo, significa che qualsiasi modello che eredita da un altro modello (astratto o non) non può utilizzare bulk_create?

risposta

2

Per la prima domanda, no non sarà possibile farlo perché obj non avrà il set di chiavi primarie e quindi non può essere utilizzato come chiave esterna.

La seconda domanda, no, non è affatto quello che dice. Indica specificamente "ereditarietà multi-tabella": l'ereditarietà da un modello astratto non è un'eredità multi-tabella.

+0

Quindi, come gestirò le relazioni con le chiavi esterne? Dovrei interrogare il database per selezionare gli oggetti che ho appena inserito? – Derek

+0

Probabilmente dovresti evitare "bulk_create" nel tuo caso. Basta creare gli oggetti individualmente. –

+7

Quindi, come si consiglia di gestire i problemi di prestazioni con singoli salvataggi? – Derek

5

Provare a impostare gli ID manualmente. Per evitare condizioni di gara, assicurati di avvolgere la funzione come una singola transazione.

from django.db import transaction, models 

@transaction.commit_on_success 
def bulk_create_with_manual_ids(foo_list): 
    id_start = (Foo.objects.all().aggregate(models.Max('id'))['id__max'] or 0) + 1 
    for i,foo in enumerate(foo_list): foo.id = id_start + i 
    return Foo.objects.bulk_create(foo_list) 

objList = [Foo(),Foo(),Foo()] 
foo_objects = bulk_create_with_manual_ids(objList) 
Bar(foo=foo_objects[0]).save() 

Si noti che questo approccio non è adatto per qualsiasi tabella che ha un campo serial o altro incremento automatico in-database chiave generata. La chiave non verrà incrementata dalla creazione in blocco poiché gli ID vengono generati dal lato Django.

+0

Questo è brutto, ma funziona! –

+0

Una singola transazione è sufficiente per evitare qualsiasi condizione di competizione? È totalmente sicuro? – kissgyorgy

+3

Ho svitato ma avrei dovuto downvoted! Il campo id non si autoincrementa nel database. Questo è un grosso problema. –