24

有没有更有效的方法来做到这一点?

for item in item_list:
    e, new = Entry.objects.get_or_create(
        field1 = item.field1,
        field2 = item.field2,
    )
4

5 回答 5

10

您无法使用 get_or_create(甚至创建)进行体面的批量插入,并且没有 API 可以轻松完成此操作。

如果您的表足够简单,使用原始 SQL 创建行不会太痛苦,那也不会太难;就像是:

INSERT INTO site_entry (field1, field2)
(
         SELECT i.field1, i.field2
         FROM (VALUES %s) AS i(field1, field2)
         LEFT JOIN site_entry as existing
                 ON (existing.field1 = i.field1 AND existing.field2 = i.field2)
         WHERE existing.id IS NULL
)

其中 %s 是一个字符串("field1, field2"), ("field3, field4"), ("field5, field6"),您必须自己正确创建和转义。

于 2010-02-12T19:13:53.853 回答
4

取决于你的目标是什么。您可以使用manage.py'loaddata函数以适当的格式(JSON、XML、YAML、...)加载数据。

另请参阅此讨论

于 2010-02-12T14:48:22.870 回答
1

从 1.4 开始,您可以执行 bulk_create

查看文档

*请注意注意事项(最重要的是不会调用模型的 save() 方法,因此不会发送 pre_save 和 post_save 信号。)*

于 2013-03-09T11:44:02.220 回答
0

我会说没有。

但我想知道你item的 s 是什么类型,如果它们有field1field2作为属性。看起来存在另一个表示条目但不是从models.Model. 也许您可以省略这个类并Entry立即创建实例而不是创建这些项目。

于 2010-02-12T14:58:36.963 回答
0

如果您不确定item_list数据库中是否已经存在您的东西,并且您需要模型对象,那么get_or_create绝对是要走的路。

如果您知道这些项目不在您的数据库中,那么您会做得更好:

for item in item_list:
    new = Entry.objects.create(
        field1 = item.field1,
        field2 = item.field2,
    )

如果您不需要这些对象,则只需忽略函数调用的返回。它不会加快数据库的速度,但如果这是一个问题,它将有助于内存管理。

如果您不确定数据是否已经在数据库中,但任一字段上都有unique=True标志,那么数据库将强制执行唯一性,您可以捕获异常并继续前进。这将通过避免尝试选择现有对象来防止额外的 DB 命中。

from django.db import IntegrityError

for item in item_list:
    try:
        new = Entry.objects.create(
            field1 = item.field1,
            field2 = item.field2,
        )
    except IntegrityError:
        continue

在任何一种情况下,您都可以通过手动管理事务来提高速度。Django 将为每次保存自动创建并提交事务,但如果您知道您将在特定函数中进行大量数据库保存,则提供一些装饰器将大大提高效率。Django 文档在解释所有这些方面做得比我在这里做得更好,但您可能需要特别注意django.db.transaction.commit_on_success

于 2010-02-12T15:42:58.350 回答