После нескольких часов попыток сделать это эффективно, я изменил свой подход к этой проблеме и определил CustomImageField
следующим образом:
class CustomImageField(ImageField):
attr_class = CustomImageFieldFile
def __init__(self, resize=False, to_width=None, to_height=None, force=True, *args, **kwargs):
self.resize = resize
if resize:
self.to_width = to_width
self.to_height = to_height
self.force = force
super(CustomImageField, self).__init__(*args, **kwargs)
class CustomImageFieldFile(ImageFieldFile):
def save(self, name, content, save=True):
super(CustomImageFieldFile, self).save(name, content, save=save)
if self.field.resize:
resized_img = resize_image(filename=self.path,
width=self.field.to_width,
height=self.field.to_height,
force=self.field.force)
if resized_img:
setattr(self.instance, self.field.width_field, resized_img.size[0])
setattr(self.instance, self.field.height_field, resized_img.size[1])
Теперь я могу просто определить:
class SomeModel(models.Model):
my_image = CustomImageField(resize=True, to_width=SOME_WIDTH, to_height=SOME_HEIGHT, force=False,
width_field='image_width', height_field='image_height')
image_width = models.PositiveIntegerField(editable=False)
image_height = models.PositiveIntegerField(editable=False)
И в зависимости от аргумента resize
размер изображения может автоматически изменяться после загрузки, а поля ширины / высоты корректно обновляются без двойного сохранения объекта. После быстрых тестов все работает нормально.