Массовое создание с моделями наследования с несколькими таблицами

Я использую модели многотабличного наследования.

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)

У меня есть представление, которое создает несколько разных моделей:

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

Очевидно, что это действительно неэффективно, поскольку создает много запросов. К сожалению, Django пока не предоставляет метод массового создания для наследования нескольких таблиц (для этого есть open pull request). Как лучше всего оптимизировать этот код? Должен ли я писать необработанный SQL-запрос или есть другой способ?

обратитесь к этому docs.djangoproject.com/en/3.1/ref/models/querysets/#bulk-cre‌​ate

harshil suthar 23.12.2020 13:56

@harshilsuthar Пожалуйста, прочитайте вопрос полностью. OP уже заявил, что изучил свои варианты и что bulk_create не работает для его варианта использования.

user1600649 23.12.2020 15:10
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
2
1 166
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я решил это, проверив реализацию bulk_create . В основе этого лежит класс InsertQuery для генерации оператора SQL INSERT INTO. ИМХО, это намного чище и короче, чем написание необработанного SQL-запроса.

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

Привет. Работает только для PostgreSQL, потому что другие механизмы баз данных не возвращают объекты со сгенерированными первичными ключами в качестве возврата от bulk_create. Это будет работать, только если вы явно определите первичный ключ для родительской модели и обработаете первичные ключи вручную.

Gustavo Gonçalves 23.01.2021 00:37

Другие вопросы по теме