Django - невозможно удалить строки при миграции назад

У меня возникла проблема. Я реализовал миграцию для создания еще одной опции в моей модели (добавить текстовый выбор preview) и реализовал метод RunPython для создания строк в таблице, которая соответствует моим требованиям. Это работает. Часть, которая не работает, - это обратный код. Я просто запрашиваю и фильтрую экземпляры, которые я хочу удалить, и пытаюсь их удалить. При этом я получаю эту странную ошибку:

Эта ошибка не имеет смысла. Есть ли у кого-нибудь предположение, что это может быть?

Код миграции:

from django.db import migrations, models


def converter(apps, schema_editor):
    AppExtension = apps.get_model("applications", "AppExtension")
    MediaType = apps.get_model("applications", "MediaType")
    MediaSize = apps.get_model("applications", "MediaSize")
    all_extensions = AppExtension.objects.all()
    media_types = []
    media_sizes = []
    for extension in all_extensions:
        mediatype_extension = MediaType(extension=extension, name="preview")
        media_types.append(mediatype_extension)
        media_sizes.append(
            MediaSize(
                media_type=mediatype_extension,
                name="intrinsic",
                width=1920,
                height=960,
            )
        )
        media_sizes.append(
            MediaSize(
                media_type=mediatype_extension,
                name="optimized",
                width=960,
                height=480,
            )
        )
    MediaType.objects.bulk_create(media_types)
    MediaSize.objects.bulk_create(media_sizes)


def reverter(apps, schema_editor):
    MediaType = apps.get_model("applications", "MediaType")
    all_extensions = AppExtension.objects.all()
    MediaType.objects.filter(
        name="preview",
    ).delete()


class Migration(migrations.Migration):

    dependencies = [
        ("applications", "0011_alter_mediatype_name"),
    ]

    operations = [
        migrations.AlterField(
            model_name="mediatype",
            name="name",
            field=models.CharField(
                choices=[
                    ("thumbnail", "Thumbnail"),
                    ("icon", "Icon"),
                    ("app-icon", "App Icon"),
                    ("preview", "Preview"),
                ],
                default="thumbnail",
                help_text="Name of this media type",
                max_length=32,
                verbose_name="Name",
            ),
        ),
        migrations.RunPython(converter, reverse_code=reverter),
    ]

Мои модели:

class MediaType(UUIDModel):
    class TypeChoices(models.TextChoices):
        THUMBNAIL = "thumbnail", "Thumbnail"
        ICON = "icon", "Icon"
        APP_ICON = "app-icon", "App Icon"
        PREVIEW = "preview", "Preview"

    extension = models.ForeignKey(
        AppExtension,
        on_delete=models.CASCADE,
        related_name="media_types",
        verbose_name=_("AppExtension"),
        help_text="AppExtension this MediaType belongs to",
    )

    name = models.CharField(
        max_length=32,
        verbose_name=_("Name"),
        help_text=f"Name of this media type",
        choices=TypeChoices.choices,
        default=TypeChoices.THUMBNAIL,
    )

    @property
    def sizes_dict(self) -> dict:
        if self.sizes.exist():
            return {size.name: size.get_tuple() for size in self.sizes.all()}
        return {}

    def __str__(self) -> str:
        return f"{self.extension.name} - {self.name}"

    class Meta:
        constraints = [
            UniqueConstraint(
                fields=["extension", "name"],
                name="unique_media_type_name_per_extension",
            ),
        ]


class MediaSize(UUIDModel):
    class SizeChoices(models.TextChoices):
        INTRINSIC = "intrinsic", "Intrinsic"
        OPTIMIZED = "optimized", "Optimized"

    media_type = models.ForeignKey(
        MediaType,
        on_delete=models.CASCADE,
        verbose_name=_("Media Type"),
        help_text="Media type this size reffers to",
        related_name="sizes",
    )

    name = models.CharField(
        max_length=32,
        verbose_name=_("Name"),
        help_text=f"Name of this media size",
        choices=SizeChoices.choices,
        default=SizeChoices.INTRINSIC,
    )

    width = models.PositiveIntegerField(
        verbose_name=_("Width"),
        help_text="Width of this media size",
    )

    height = models.PositiveIntegerField(
        verbose_name=_("Height"),
        help_text="Height of this media size",
    )

    def get_tuple(self) -> Tuple[int, int]:
        return self.width, self.height

    def __str__(self) -> str:
        return (
            f"{self.media_type.extension.name} - {self.media_type.name}"
            + f" - {self.name}: ({self.get_tuple()})"
        )

    class Meta:
        constraints = [
            UniqueConstraint(
                fields=["media_type", "name"],
                name="unique_media_size_name_per_media_type",
            ),
            UniqueConstraint(
                fields=["media_type", "height", "width"],
                name="unique_media_size_dimensions_per_media_type",
            ),
        ]
  • Попробовал выполнить точно такой же код для удаления строк вне миграции -> работает
  • .
  • Попробовал остановить миграцию между ними, получить единственный экземпляр вложенного типа MediaSize и удалить его -> выдает ту же ошибку
  • Запуск миграции с отладчиком vscode и без него приводит к той же ошибке
  • .
  • Во время миграции можно обновлять и сохранять экземпляр, только операция удаления вызывает эту ошибку
  • .

Попробуйте просто удалить reverse_code. Я не думаю, что он вам нужен, поскольку операция не нуждается в реверсировании.

Вернуться на верх