首页 > 解决方案 > 数据迁移以替换 TextField 中的单词实例?

问题描述

我正在编写一个数据迁移来通过一些用于发送通知的通用模板,目的是将“word1”的所有实例更改为“word2”。'word1' 可以出现在模板的名称和正文中。目前,只有一个名称中带有“word1”的模板,因此我可以使用 if 语句轻松更改该模板,该语句获取该确切名称并将其替换为所需的名称。我遇到的问题是当它出现在模板正文中时将 'word1' 与 'word2' 交换。另外需要注意的是,正文中“word1”的出现完全独立于名称中的出现。

到目前为止,我已经尝试a_notification.body.contains('word1')在我的 for 循环中使用 if 语句来查找哪些通知包含该单词。我还尝试将正文拆分为单词列表,将文本字段按空格字符拆分,然后使用 for 循环检查每个单词是否等于“word1”。目前,我正在尝试使用 .replace() 来查找实例并将其替换为所需的单词。

迁移文件:

#Generated by Django 1.11.6 on 2019-07-08 20:05
from __future__ import unicode_literals

from django.db import migrations

def word1_to_word2(apps, schema_editor):
    notification = apps.get_model('hr', 'NotificationTemplate')
    for a_notification in notification.objects.all():
        #change the name of template that needs to be changed
        if a_notification.name == 'Name with word1':
            a_notification.name = 'Name with word2'

        #Loop through body of template and change the instances
        if 'word1' in a_notification.body in a_notification.body:
            a_notification.body.replace('word1', 'word2')
        a_notification.save()

class Migration(migrations.Migration):

    dependencies = [
        ('hr', '0013_rename_fieldA'),
    ]

    operations = [
        migrations.RunPython(word1_to_word2),
    ]

模型.py

class Notification(models.Model):

    title = models.CharField(
        max_length=100, default="UREC Message", db_index=True)
    sender = models.ForeignKey(User)

    # Recepients
    employee_recepients = models.ManyToManyField(Employee, blank=True)

    # Email Pieces
    template = models.ForeignKey(NotificationTemplate, blank=True, null=True)
    signature = models.ForeignKey(NotificationSignature, blank=True, null=True)
    date_created = models.DateTimeField(auto_now_add=True)
    date_sent = models.DateTimeField(null=True)
    body = models.TextField(blank=True)

标签: pythondjangodata-migration

解决方案


这不起作用的原因是字符串是不可变的。Asome_string.replace(..)不会更改字符串,它会创建一个新字符串。

因此,您可以使用以下方法调用它:

a_notification.body = a_notification.body.replace('word1', 'word2')

话虽如此,这是相当低效的,因为您对每个对象进行查询。从Replace表达式 [Django-doc]进行两次批量更新:

from django.db.models import Value
from django.db.models.functions import Replace

def word1_to_word2(apps, schema_editor):
    notification = apps.get_model('hr', 'NotificationTemplate')
    notification.objects.update(name=Replace('name', Value('word1'), Value('word2')))
    notification.objects.update(body=Replace('body', Value('word1'), Value('word2')))

推荐阅读