Почему моя миграция данных Django с поля ForeignKey на OneToOneField не работает?
У меня есть несколько моделей с полем ForeignKey, которое указывает на другую модель:
class Specimen(models.Model):
...
class ResultA(models.Model):
specimen = models.ForeignKey(Specimen, on_delete=models.CASCADE, ...)
...
class ResultB(models.Model):
specimen = models.ForeignKey(Specimen, on_delete=models.CASCADE, ...)
...
В какой-то момент я понял, что каждый образец будет иметь только ноль или один результат каждого типа, так что, вероятно, имеет смысл превратить это в OneToOneField
.
План заключается в следующем:
- Создайте дополнительное поле
specimen_new
, которое будетOneToOneField
на каждом результате - Создайте миграцию данных, которая переместит данные из поля
ForeignKey
в полеOneToOneField
- Удалите поле
ForeignKey
- Переименуйте новое
specimen_new
OneToOneField
в простоspecimen
- Обновите все ссылки на код, чтобы правильно использовать новый
OneToOneField
Шаг 1 был довольно простым:
class Specimen(models.Model):
...
class ResultA(models.Model):
specimen = models.ForeignKey(Specimen, on_delete=models.CASCADE, ...)
specimen_new = models.OneToOneField(Specimen, on_delete=models.CASCADE, ...)
...
class ResultB(models.Model):
specimen = models.ForeignKey(Specimen, on_delete=models.CASCADE, ...)
specimen_new = models.OneToOneField(Specimen, on_delete=models.CASCADE, ...)
...
Я застрял на шаге 2 - создание миграции данных.
Сейчас это выглядит следующим образом:
from django.db import migrations
def migrate_results(apps, schema_editor):
# Get the model
Specimen = apps.get_model('ahs', 'Specimen')
# Update every specimen
for specimen in Specimen.objects.filter():
for field in Specimen._meta.get_fields():
# Look for fields that end with "_new"
if field.name.endswith("_new"):
old_field_name = field.name[:-4] # Without the suffix
new_field_name = field.name
# Try to get the result
result = getattr(specimen, old_field_name).first()
# If the field had a result, copy it to the new OneToOneField
if result:
setattr(specimen, new_field_name, result)
specimen.save()
class Migration(migrations.Migration):
dependencies = [
('ahs', '0009_auto_20220525_0827'),
]
operations = [
migrations.RunPython(migrate_results),
]
Насколько я могу судить, это должно работать, и это не приводит к сбоям. Операторы печати в миграции (не показаны выше) показывают, что данные копируются. Но когда я запускаю миграцию, ни один из данных не был скопирован в OneToOneField
.
Есть ли что-то, что я явно делаю неправильно?