在Django中批量创建模型对象


90

我有很多对象要保存在数据库中,因此我想用它创建Model实例。

使用django,我可以使用创建所有模型实例,MyModel(data)然后将其全部保存。

目前,我有这样的事情:

for item in items:
    object = MyModel(name=item.name)
    object.save()

我想知道是否可以直接保存对象列表,例如:

objects = []
for item in items:
    objects.append(MyModel(name=item.name))
objects.save_all()

如何在一次交易中保存所有对象?


似乎正在为实现此代码而
ticket /

1
想知道list.save_all吗?您几乎可以回答自己,只是解释一下想知道的问题,并使用主题问题中的2个头文字。
斯瓦沃米尔Lenart

Answers:


95

在django开发中,存在bulk_create一个对象管理器方法,该方法将使用类构造函数创建的对象数组作为输入。查看Django文档



1
但是请记住,bulk_create具有一些局限性,例如,如果它是save()自动执行的AutoField,则它不会创建主键。
Hitesh Garg,2015年

@HiteshGarg,现在还是这样吗?
Raydel Miranda

1
@RaydelMiranda,是的,它仍然是正确的。它就在文档中:If the model’s primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does, unless the database backend supports it (currently only PostgreSQL).
interDist

1
我使用Django 3.0.x并确认使用bulk_create()不会触发任何信号。我想知道为什么。
enchance

42

使用bulk_create()方法。现在是Django中的标准。

例:

Entry.objects.bulk_create([
    Entry(headline="Django 1.0 Released"),
    Entry(headline="Django 1.1 Announced"),
    Entry(headline="Breaking: Django is awesome")
])

1
Django 1.10中的更改:添加了对在使用PostgreSQL时使用bulk_create()创建的对象设置主键的支持。
elad silver

4

我为循环使用手动事务处理(postgres 9.1)工作:

from django.db import transaction
with transaction.commit_on_success():
    for item in items:
        MyModel.objects.create(name=item.name)

实际上,它与“本机”数据库批量插入不同,但是它允许您避免/减少传输/ orms操作/ sql查询分析成本


1
这有一点改变。现在交易commit_on_success不再存在。您应该使用transaction.atomic():见stackoverflow.com/questions/21861207/...
t_io

4

这是从列分隔文件中批量创建实体的方法,不包括所有未引用和未转义的例程:

SomeModel(Model):
    @classmethod
    def from_file(model, file_obj, headers, delimiter):
        model.objects.bulk_create([
            model(**dict(zip(headers, line.split(delimiter))))
            for line in file_obj],
            batch_size=None)

3

对于单行实现,可以在地图中使用lambda表达式

map(lambda x:MyModel.objects.get_or_create(name=x), items)

在此,lambda将项目列表中的每个项目与x匹配,并在必要时创建数据库记录。

Lambda文档


你可能想提及的是,lambda必须要mapPED在itemsmap(lambda name: MyModel.objects.get_or_create(name = name), items)
马诺Govindan

Ja,那是我尝试说的另一种方式(:
FallenAngel 2010年

2

使用create会导致每个新项目一个查询。如果要减少INSERT查询的数量,则需要使用其他方法。

我使用了Bulk Insert代码段,即使代码段很旧,也取得了一些成功。可能需要进行一些更改才能使其再次运行。

http://djangosnippets.org/snippets/446/


2

bulkops模块上查看此博客文章。

在django 1.3应用程序上,我经历了明显的加速。


-19

最简单的方法是使用createManager方法,该方法只需一步即可创建和保存对象。

for item in items:
    MyModel.objects.create(name=item.name)

+1。如果name是唯一的并且可以重复输入,那么使用将是一个好主意get_or_create
Manoj Govindan

16
这如何回答这个问题?Model.objects.create等效于object = MoModel(..)object.save()。而且,这并不会在一笔交易中做到这一点……
automagic 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.