0

这是一些数据库高尔夫。假设我有一个对象:

class A(models.Model):
     b = models.ManyToManyField(B)
     #Many other fields

现在假设我想对字段 b 进行批量更新。

some_objects = A.filter(q).values('id','b')
#Populate a map of ids
related_map = {
    some_objects[0]['id']: [1,2],
    some_objects[1]['id']: [1],
    #etc.
}

现在我想做的是这样的:

for (id,related_ids) in related_map.iteritems():
    A.filter(id=id).update(b=related_ids)

这会引发 FieldError。当然,我可以这样做

for (id,related_ids) in related_map.iteritems():
    a = A.objects.get(id=id)
    a.b = related_ids

这行得通,但似乎没有必要。我已经从数据库中提取了我需要的所有数据,以便填充related_map。有没有一种内置的方法可以在不查询数据库的情况下更新多对多?

4

1 回答 1

1

我认为 ORM 不会暴露这一点,除非您为关系声明中间模型。如果您不需要任何特殊行为(如触发信号),您应该可以通过直接 SQL 调用来完成。就像是:

field = A._meta.get_field_by_name('b')[0]
tablename = field.m2m_db_table()
column_a_name = field.m2m_column_name()
column_b_name = field.m2m_reverse_name()

from django.db import connection, transaction
cursor = connection.cursor()
for (id, related_ids) in related_map.iteritems():
    for related_id in related_ids:
        cursor.execute("insert into %s (%s, %s) values (%s, %s)", (tablename, column_a_name, column_b_name, id, related_id))
transaction.commit_unless_managed()

https://docs.djangoproject.com/en/1.5/topics/db/sql/#executing-custom-sql-direct有完整的文档和事务控制选项的讨论。

这些字段查找不是文档化 API 的一部分,因此在未来的版本中可能存在更改的风险。

于 2013-08-20T19:44:42.717 回答