2014-01-30 76 views
14

我想更新和修改字符串字段Django的ORM。等效SQL要做到这一点:Django批量更新字符串替换

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

随着该查询,我希望old textold text more textnew textnew text more text分别被替换,在string_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相关的问题:

+0

我也碰到这个问题回到那里。我能找到的最好的方法是在Python代码中进行字符串处理。如果您不介意使用原始SQL,则任何数据库之间的替换函数都是非常一致的。 –

回答

4

你可以使自己的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对象不无论如何,似乎都可以使用字符串。

+0

任何想法Django版本和DBMS支持这是什么? –

+0

不确定。我刚刚在1.6.6上试了一下;我预计它可以在(很多)早期版本中工作,但不确定具体情况。在SQL方面,'REPLACE'函数似乎至少以Postgres,MySQL和SQLite的形式存在。 –

8

测试和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

工作于**'1.8 +'** https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions和PostgreSQL –

+1

已确认与django合作1.11.2 – user1330734