Home > Back-end >  Bulk create for models with a foreign key
Bulk create for models with a foreign key

Time:09-17

I have these two models:

class Item(models.Model):
    item_id = models.CharField(max_length=10, primary_key=True)
    item_name = models.CharField(max_length=100)
    description = models.CharField(max_length=500)
    slug = models.CharField(max_length=200)
    price = models.FloatField()
    
    def __str__(self):
        return self.item_name
class Image(models.Model):
    item = models.ForeignKey(Item, on_delete=models.CASCADE)
    image_url = models.CharField(max_length=200)

I have a lot of items, and each Item has some images assigned to it.

To add items in the database, I do it through a bulk create:

    it = (Item(
            item_id = item['id'],
            item_name= item['title'],
            description = item['description'],
            slug = item['slug'],
            price =  item['price']['amount']
            )
        for item in items
    )
    while True:
        batch = list(islice(it, batch_size))
        if not batch:
            break
        Item.objects.bulk_create(batch, batch_size)

This works perfectly fine, ok. But I want to do the same with the images, since I have too many images to do it individually.

For now I do it like this:

for item in items:
    for image in item['images']:
        Item.objects.get(item_id = item['id']).image_set.create(image_url = image['urls']['big'])

But this is too slow in uplaoding all the Images (it may take 30 minutes), so I want to upload in bulk like I do it with Item, but since Image model has Item as a foreign key, I cannot do it the same way. How can I upload Images in a more efficient manner?

I am using SQLite, I know that using another database system would speed up the process, but anyway, I think there is a faster way to upload all the Images.

Thanks.

CodePudding user response:

You can make Image objects in bulk as well, with:

images = [
    Image(item_id=item['id'], image_url=image['urls']['big'])
    for item in items
    for image in item['images']
]
Image.objects.bulk_create(images)

Here we thus make use if the item_id=item['id'] to set a value for the ForeignKey later, and then insert these all in bulk in the database.

This works because if you define field named fieldname as a ForeignKey, Django allows you to work with fieldname_id to specify the value for the to field referenced by that ForeignKey.

  • Related