使用字符串替换的Django批量更新

时间:2014-01-30 18:42:13

标签: python django django-orm

我正在尝试更新和修改字符串字段Django的ORM。执行此操作的等效SQL是:

UPDATE example_table SET string_field = REPLACE(string_field, 'old text', 'new text');

对于old text列中的所有条目,对于该查询,我希望old text more textnew text分别替换为new text more textstring_field

Bulk update()似乎很有希望,但不允许我仅修改字段的一部分,而F() expressions只实现数字更改,而不是字符串替换。我还看了使用raw queries来运行上面的SQL,但这似乎是一个侧面的黑客(特别是因为F()存在以对数字执行相同的功能),我无法让它们实际执行。

我最终得到了这个,但是当我知道有一行SQL语句来执行所有额外的查询时,这似乎是一种耻辱。

for entry in ExampleModel.objects.all():
    entry.string_field = entry.string_field.replace('old text', 'new text', 1)
    entry.save()

对于字符串,Django的ORM中是否不存在此功能?在文档中有没有我忽略的东西?

相关的SO问题:

4 个答案:

答案 0 :(得分:17)

使用django 1.9进行测试

from django.db.models import F, Func, Value

ExampleModel.objects.filter(<condition>).update(
    string_field=Func(
        F('string_field'),
        Value('old text'), Value('new text'),
        function='replace',
    )
)

答案 1 :(得分:5)

您可以创建自己的F - 类似对象来表示SQL中的字符串替换。这是一个概念证明:

from django.db.models.expressions import ExpressionNode

class StringReplaceF(ExpressionNode):
    def __init__(self, field, replace_from, replace_to):
        self.field = field
        self.replace_from = replace_from
        self.replace_to = replace_to
        super(StringReplaceF, self).__init__()

    def evaluate(self, evaluator, qn, connection):
        return (
            "REPLACE({}, %s, %s)".format(self.field),
            (self.replace_from, self.replace_to)
        )

 >>> f = StringReplaceF('string_field', 'old text', 'new text')
 >>> ExampleModel.objects.update(string_field=f)

如果你需要它与其他F对象表现良好,你需要对该类做更多的工作,但是再一次,现有的F对象似乎不起作用无论如何都要用琴弦。

答案 2 :(得分:1)

Django 2.1的新功能-Replace database function

您的示例现在可以通过以下方式最轻松地表达:

ExampleModel.objects.update(string_field=Replace('string_field'), Value('old_text'), Value('new_text'))

答案 3 :(得分:0)

Django 2.2支持批量更新,您可以使用其中一个功能。

选中一项:https://docs.djangoproject.com/en/2.2/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create