Reputation: 95
I am writing a data migration to go through some general templates used to send notifications with the goal of changing all instances of 'word1' to 'word2'. 'word1' can occur in both the name of the template as well as the body. Currently, there is only one template with 'word1' in the name, so I am able to change that one easily with an if statement that grabs that exact name and replaces it with the desired name. The issue I am running into is swapping 'word1' with 'word2' when it appears in the body of a template. An additional note to make is that the occurrences of 'word1' in the body are independent entirely from the occurrences in the name.
So far, I've tried using an if statement with a_notification.body.contains('word1')
in my for loop to find which notifications contain that word. I've also tried splitting up the body into a list of words, splitting the textfield by space characters, and then using a for loop to check each individual word to see if it is equal to 'word1'. Currently, I am trying to use .replace() to find the instance and replace it with the desired word.
Migration file:
#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),
]
models.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)
Upvotes: 1
Views: 256
Reputation: 476594
The reason why this did not work is because strings are immutable. A some_string.replace(..)
does not change the string, it creates a new one.
You thus can call this with:
a_notification.body = a_notification.body.replace('word1', 'word2')
That being said, this is rather inefficient, since you do a query per object. Since django-2.1, you can make two bulk updates with a Replace
expression [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')))
Upvotes: 2