Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bulk create with multi-table inheritance models

Tags:

python

django

I'm using multi-table inheritance models.

from django.db import models

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)
    serves_pizza = models.BooleanField(default=False)

class Cinema(Place):
    sells_tickets = models.BooleanField(default=False)
    sells_popcorn = models.BooleanField(default=False)

class Coffee(Place):
    sells_tea = models.BooleanField(default=False)

I have a view that creates several different models:

items = [
    Restaurant(...),
    Restaurant(...),
    Restaurant(...),
    Cinema(...),
    Cinema(...),
    Coffee(...),
    Coffee(...),
    # + 1.000 other items
]
for item in items:
    item.save()

Obviously, this is really inefficient since it creates a lot of queries. Unfortunately, Django doesn't provide a bulk-create method for multi-table inheritance yet (there is an open pull request for it). What is the best way to optimize this code? Do I have to write a raw SQL query or is there another way?

like image 584
Nepo Znat Avatar asked Sep 05 '26 19:09

Nepo Znat


1 Answers

I solved it by inspecting the implementation of bulk_create. Underlying it uses the InsertQuery class to generate the SQL INSERT INTO statement. IMHO this is much cleaner and shorter than writing a raw SQL query.

# Create all concrete models at once
items = Place.objects.bulk_create(items)

# Group items by their model
item_mapping = defaultdict(list)
for item in items:
    item_mapping[type(item)].append(item)

# Create a bulk insert for each model
for model, items in item_mapping.items():
    fields = model._meta.local_concrete_fields
    query = sql.InsertQuery(model)
    query.insert_values(fields, items)
    query.get_compiler(connection=connection).execute_sql()
like image 102
Nepo Znat Avatar answered Sep 07 '26 07:09

Nepo Znat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!