From 001da1d04816d2580a1b44e802a09ce29163d976 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 20 May 2022 18:35:42 +0200 Subject: [PATCH] Add support to migrate from django-stimage --- pictures/migrations.py | 12 ++++++++-- tests/test_migrations.py | 49 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/pictures/migrations.py b/pictures/migrations.py index 686f338..6a057b4 100644 --- a/pictures/migrations.py +++ b/pictures/migrations.py @@ -35,7 +35,7 @@ def alter_picture_field( if not isinstance(from_field, PictureField) and isinstance( to_field, PictureField ): - self.to_picture_field(to_model) + self.to_picture_field(from_model, to_model) elif isinstance(from_field, PictureField) and not isinstance( to_field, PictureField ): @@ -63,7 +63,15 @@ def from_picture_field(self, from_model: Type[models.Model]): field_file = getattr(obj, self.name) field_file.delete_all() - def to_picture_field(self, to_model: Type[models.Model]): + def to_picture_field( + self, from_model: Type[models.Model], to_model: Type[models.Model] + ): + from_field = from_model._meta.get_field(self.name) + if hasattr(from_field.attr_class, "delete_variations"): + # remove obsolete django-stdimage variations + for obj in from_model._default_manager.all().iterator(): + field_file = getattr(obj, self.name) + field_file.delete_variations() for obj in to_model._default_manager.all().iterator(): field_file = getattr(obj, self.name) field_file.save_all() diff --git a/tests/test_migrations.py b/tests/test_migrations.py index 2d2570b..a758873 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -3,6 +3,7 @@ import pytest from django.core.management import call_command from django.db import models +from django.db.models.fields.files import ImageFieldFile from pictures import migrations from pictures.models import PictureField @@ -156,6 +157,51 @@ def test_from_picture_field(self, stub_worker, image_upload_file): @pytest.mark.django_db def test_to_picture_field(self, request, stub_worker, image_upload_file): + class FromModel(models.Model): + picture = models.ImageField() + + class Meta: + app_label = request.node.name + db_table = "testapp_profile" + + class ToModel(models.Model): + name = models.CharField(max_length=100) + picture = models.ImageField(upload_to="testapp/profile/") + + class Meta: + app_label = request.node.name + db_table = "testapp_profile" + + luke = ToModel.objects.create(name="Luke", picture=image_upload_file) + stub_worker.join() + migration = migrations.AlterPictureField("profile", "picture", PictureField()) + migration.to_picture_field(FromModel, Profile) + stub_worker.join() + luke.refresh_from_db() + path = ( + Profile.objects.get(pk=luke.pk) + .picture.aspect_ratios["16/9"]["WEBP"][100] + .path + ) + assert path.exists() + + @pytest.mark.django_db + def test_to_picture_field__from_stdimage( + self, request, stub_worker, image_upload_file + ): + class StdImageFieldFile(ImageFieldFile): + delete_variations = Mock() + + class StdImageField(models.ImageField): + attr_class = StdImageFieldFile + + class FromModel(models.Model): + picture = StdImageField() + + class Meta: + app_label = request.node.name + db_table = "testapp_profile" + class ToModel(models.Model): name = models.CharField(max_length=100) picture = models.ImageField(upload_to="testapp/profile/") @@ -167,7 +213,7 @@ class Meta: luke = ToModel.objects.create(name="Luke", picture=image_upload_file) stub_worker.join() migration = migrations.AlterPictureField("profile", "picture", PictureField()) - migration.to_picture_field(Profile) + migration.to_picture_field(FromModel, Profile) stub_worker.join() luke.refresh_from_db() path = ( @@ -176,6 +222,7 @@ class Meta: .path ) assert path.exists() + assert StdImageFieldFile.delete_variations.called @pytest.mark.django_db(transaction=True) def test_database_backwards_forwards(self):