在mysql中,您可以在一个查询中为n> 0插入多行到一个表中:
INSERT INTO tbl_name (a,b,c) VALUES(1,2,3),(4,5,6),(7,8,9), ..., (n-2, n-1, n);
有没有一种方法可以使用Django queryset方法实现以上目标?这是一个例子:
values = [(1, 2, 3), (4, 5, 6), ...] for value in values: SomeModel.objects.create(first=value[0], second=value[1], third=value[2])
我相信上面为for循环的每次迭代都调用了插入查询。我正在寻找一个查询,这在Django中可能吗?
最近,我本人也在寻找这样的东西(受到QuerySet.update()的启发,就像我想的那样)。据我所知,当前的生产框架(截至目前为1.1.1)中不存在大量创建的内容。我们最终为需要批量创建的模型创建了一个自定义管理器,并在该管理器上创建了一个函数,以使用VALUES参数序列构建适当的SQL语句。
诸如此类的东西(如果无法解决,请您道歉…希望我已经从我们的代码中很好地适应了这一点):
from django.db import models, connection class MyManager(models.Manager): def create_in_bulk(self, values): base_sql = "INSERT INTO tbl_name (a,b,c) VALUES " values_sql = [] values_data = [] for value_list in values: placeholders = ['%s' for i in range(len(value_list))] values_sql.append("(%s)" % ','.join(placeholders)) values_data.extend(value_list) sql = '%s%s' % (base_sql, ', '.join(values_sql)) curs = connection.cursor() curs.execute(sql, values_data) class MyObject(models.Model): # model definition as usual... assume: foo = models.CharField(max_length=128) # custom manager objects = MyManager() MyObject.objects.create_in_bulk( [('hello',), ('bye',), ('c', )] )
这种方法确实存在特定于特定数据库的风险。在我们的例子中,我们希望函数返回刚刚创建的ID,因此我们在函数中进行了postgres特定的查询,以从代表对象的表的主键序列中生成所需数量的ID。也就是说,与迭代数据和发出单独的QuerySet.create()语句相比,它在测试中的性能确实要好得多。