Django: update_or_create, фильтр со списком kwargs - PullRequest
0 голосов
/ 20 июня 2019

Есть ли способ использовать список в фильтре kwargs update_or_create?

Вот мои модели:

class Partner:
    ...

class MyClassB:
    partner = models.OnetoOneField(Partner, related_name='some_name')
    ....

Я попытался использовать цикл for, и он отлично работает.

# partners = list of queryset objects.

for partner in partners:
    MyClassB.objects.update_or_create(partner=partner, defaults= 
    {'name': None})

Эта операция используется очень часто, и я думал об оптимизации этого update_or_create. Могу ли я обновить всех партнеров за один раз? Что-то вроде:

MyClassB.objects.update_or_create(partner__in=[partners], defaults={'name': None})

Этот код является частью API, который будет проверяться тысячами партнеров каждые 5 секунд. И я хочу избежать дополнительных затрат на использование цикла for здесь. Есть ли оптимизированный способ?

Ответы [ 2 ]

1 голос
/ 20 июня 2019
MyClassB.objects.update_or_create(partner__in=[i.pk for i in Partner.objects.all()], defaults={'name': None})

вы можете использовать это понимание списка в той же строке. или создайте список и перейдите к квестам

partners = []
partner = Partner.objects.all() // or some filter
for i in partner:
    partners.append(i.pk)

MyClassB.objects.update_or_create(partner__in=partners, defaults={'name': None})
0 голосов
/ 20 июня 2019

Ну, насколько я знаю, update_or_create предназначен для использования с одним объектом, а не со многими.

Но внутри него он ищет в БД, если запись существует, и если да, обновляет ее, в противном случае создает новую.

Поскольку create_or_update выполняет два запроса, вы можете выполнить следующие действия без особых накладных расходов:

  1. Получить все записи, которые уже существуют:
existing_db_partners = set(MyClassB.objects.filter(partner__in=partners).values_list('id', flat=True))
  1. Теперь создайте два списка: один с существующими партнерами, другой с теми, которые этого не делают:
to_update = [partner 
             for partner in partners 
             if partner.id in existing_db_partners]

to_create = [partner 
             for partner in partners 
             if partner.id not in existing_db_partners]
  1. На данный момент это очень просто. Обновите to_update, создайте to_create, используя bulk_create и bulk_update

Я не могу думать ни о чем быстрее

Примечание: это не было проверено.

...