In mysql, you can insert multiple rows to a table in one query for 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循环的每个迭代调用一个insert查询.我在找一个问题,在Django有可能吗?

推荐答案

我最近自己也在寻找这样的东西(灵感来自QuerySet.update(),我想你也是).据我所知,目前的生产框架(截至今天的1.1.1)中不存在批量创建.最后,我们为需要批量创建的模型创建了一个自定义管理器,并在该管理器上创建了一个函数,以使用值序列参数构建适当的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()语句相比,它在测试中的性能要好得多.

Django相关问答推荐

Django:如何 Select 没有其他项目引用的项目?

如何访问 django 模板中的字典值?

Django 关系嵌套related_name

如何根据查询集中的条件返回多个聚合?

如何在 Django 视图中获取 URL 参数?

在 Django 管理员中嵌套内联?

Django-获取外键模型

OrderingFilter 没有属性filter_queryset

Django:如何在视图中获取格式日期?

使用 Django 1.5 实现多种用户类型

Celery 和 Django 简单示例

Python 社区里的小马是怎么回事?

在 Django Admin 中过滤多对多框

如何在字段集中显示 Django 管理内联模型?

登录后django重定向不起作用next不发布?

显式 cursor.close() 的必要性

如何过滤(或替换)在 UTF-8 中占用超过 3 个字节的 unicode 字符?

Django将整数模型字段的范围设置为约束

Numpy 数组到 base64 并返回到 Numpy 数组 - Python

django/文件上传权限