Python 如何使用Django ORM执行大容量插入或增量类型操作

Python 如何使用Django ORM执行大容量插入或增量类型操作,python,django,postgresql,Python,Django,Postgresql,我有一个定义如下的模型: class VectorSet(models.Model): word = models.CharField(max_length=255) weight = models.IntegerField() session = models.ForeignKey(ResearchSession) 我想写一个函数,它将获取一个单词列表和一个研究会话,对于该单词列表中的每个单词,如果它不存在,则创建一个权重为1的新行,否则,获取该行并将权重增加1 到目

我有一个定义如下的模型:

class VectorSet(models.Model):
    word = models.CharField(max_length=255)
    weight = models.IntegerField()
    session = models.ForeignKey(ResearchSession)
我想写一个函数,它将获取一个单词列表和一个研究会话,对于该单词列表中的每个单词,如果它不存在,则创建一个权重为1的新行,否则,获取该行并将权重增加1

到目前为止,我已经了解到:

def train(words, session):
    for i in words:
        result, created = VectorSet.objects.get_or_create(word=i, session=session,
                                                          defaults={'weight' : 1})
        if not created:
            result.weight = F('weight') + 1
            result.save()

我很有信心,有一种方法可以通过一个查询实现这一点,但是我不太清楚这可能是什么,或者是否可以通过原始SQL使用django代码。

除了我认为的以外,目前没有现成的解决方案来进行批量插入。另一种解决方案(取决于您的数据库)是使用在事务中执行get_或_create。例如:

from django.db import transaction

@transaction.atomic
def train(words, session):
    for i in words:
        result, created = VectorSet.objects.get_or_create(word=i, session=session,
                                                      defaults={'weight' : 1})
        if not created:
            result.weight = F('weight') + 1
            result.save()
否则,您可能可以使用DB API:


逻辑很简单,但我们需要多次点击DB,这意味着需要多次查询:

qs = VectorSet.objects.filter(word__in=words, session=session)
qs.update(weiget=models.F('weight')+1)
VectorSet.objects.bulk_insert(VectorSet(session=session, word=w, weight=1)
  for w in words if w not in qs.value_list('word', flat=True))
Django 1.7中也有一个默认值,但目前它没有区分update的默认值和create的默认值:

for w in words:
    VectorSet.objects.update_or_create(word=w, session=session,
                                    defaults={'weight': models.F('weight')+1})

因此,上面的代码将无法通过intmodels创建。F'weight'+1我们可以覆盖uuu int_uuuu方法,但太过粗糙而没有意义……IMO

至少相关:在我看来非常好。
for w in words:
    VectorSet.objects.update_or_create(word=w, session=session,
                                    defaults={'weight': models.F('weight')+1})