使用Django ORM生成更新查询

11

我需要使用Django ORM实现这个查询:

update table set field=field+1 where id=id

我不想使用这个:

o = model.objects.get(id=id)
o.field+=1
o.save()

因为它使用选择和更新,并且不是线程安全的。

如何通过ORM实现这一点?

4个回答

37

之前的两位回答者都有一部分解决方案:你应该使用F()update结合使用:

Model.objects.filter(id=id).update(field=F('field') +1))

请注意,此操作会直接进行更新,无需任何SELECT操作。


2
您可以使用update命令,详细信息可在文档中查找。

OP想以线程安全的方式根据现有字段更新属性,这可以通过F()表达式完成。我不认为update具有这样的功能。你确定吗? - jurgenreza

1

对于 django v2.2(可能也适用于3+),SQL语句编译函数如下:

from django.db.models.sql.subqueries import UpdateQuery

def compile_update_query(query_set, update_kwargs):
    query = query_set.query.chain(UpdateQuery)
    query.add_update_values(update_kwargs)
    return str(query)

其中query_setMyShinyModel.objects.filter(id=42)update_kwargs是要更新的模型字段的字典。


0
如果您需要将UPDATE ORM查询转换为UPDATE SQL语句而不执行它,可以使用以下方法:

update()方法会立即应用并返回查询匹配的行数(django 1.8文档)

def generate_update_sql(queryset, update_kwargs):
    """  [checked on django 1.8]
    Converts queryset with update_kwargs
    like if was: queryset.update(**update_kwargs)
    """
    from django.db.models import sql

    query = queryset.query.clone(sql.UpdateQuery)
    query.add_update_values(update_kwargs)
    compiler = query.get_compiler(queryset.db)
    sql, params = compiler.as_sql()
    return sql % params

使用方法

qs = Event.objects.exclude(app='some')
update_kwargs = dict(description='test', action='action')
generate_update_sql(qs, update_kwargs) 

将返回

UPDATE `api_event` SET `description` = test, `action` = action WHERE NOT (`api_event`.`app` = some)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接