Django:update_or_create,使用kwargs列表进行过滤

时间:2019-06-20 06:19:23

标签: python django django-models django-queryset

update_or_create的kwargs过滤器中有没有使用列表的方法?

这是我的模特:

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秒将有1000个合作伙伴点击该代码。而且我想避免在这里使用for循环的额外开销。有什么优化的方法吗?

2 个答案:

答案 0 :(得分:1)

MyClassB.objects.update_or_create(partner__in=[i.pk for i in Partner.objects.all()], defaults={'name': None})

您可以在同一行中使用此列表理解功能。或创建列表并传递到quesyset

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

答案 1 :(得分:0)

据我所知,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. 在这一点上,这很容易。使用bulk_create和bulk_update更新to_update,创建to_create

我想不出什么快事

注意:这尚未经过测试。