2012-05-29 19 views
10

que estaba leyendo sobre Django bulk_create y algunos de sus "defectos":¿Usando Django bulk_create objetos en claves foráneas?

" 
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. 
" 

no entendía completamente. Así que si tengo una lista de objetos, pasarlo a bulk_create:

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

¿Podría seguir utilizando claves foráneas en estos objetos finos?

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

¿La relación ForeignKey será correcta? También cuando dice 2. No funciona con modelos secundarios en un escenario de herencia de tablas múltiples, significa que cualquier modelo que herede de otro modelo (abstracto o no) no puede usar bulk_create?

Respuesta

2

Para la primera pregunta, no, no será capaz de hacer eso, porque obj no tendrá su clave primaria establecido por lo que no podría ser utilizado como una clave externa.

La segunda pregunta, no, eso no es lo que dice en absoluto. Menciona específicamente "herencia de tablas múltiples": heredar de un modelo abstracto no es herencia de tablas múltiples.

+0

Entonces, ¿cómo manejaría las relaciones de clave externa? ¿Tendría que consultar la base de datos para seleccionar los objetos que acabo de insertar? – Derek

+0

Probablemente deberías evitar 'bulk_create' por completo en tu caso. Solo crea los objetos individualmente. –

+7

Entonces, ¿cómo recomiendas manejar los problemas de rendimiento con hacer salvaciones individuales? – Derek

5

Intente configurar los identificadores manualmente. Para evitar condiciones de carrera, asegúrese de ajustar la función como una transacción única.

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() 

Tenga en cuenta que este método no es adecuado para cualquier tabla que tiene un campo serial u otro incremento automático en la base de datos de claves generado. La clave no se incrementará en la creación masiva ya que las ID se están generando en el lado de Django.

+0

Esto es feo, pero funciona! –

+0

¿Es suficiente una sola transacción para evitar cualquier condición de carrera? ¿Es totalmente seguro? – kissgyorgy

+3

He votado, pero debería haber votado negativamente. El campo de identificación no se autoincrementa en la base de datos. Este es un gran problema. –

Cuestiones relacionadas