def save_image_and_mobile(instance, image_field, image_url_field, mobile_image_field):
if getattr(instance, image_url_field):
response = requests.get(getattr(instance, image_url_field))
if response.status_code == 200:
content_type = response.headers.get('Content-Type')
if content_type:
extension = mimetypes.guess_extension(content_type)
parsed_url = urlparse(getattr(instance, image_url_field))
filename = unquote(parsed_url.path.split("/")[-1]) + extension
temp_file = File(io.BytesIO(response.content), name=filename)
getattr(instance, image_field).save(filename, temp_file, save=False)
setattr(instance, image_url_field, None)
img = Image.open(temp_file)
# Вычисляем новые размеры с сохранением пропорций
width, height = img.size
if width > height:
new_width = 400
new_height = int(400 / width * height)
else:
new_height = 400
new_width = int(400 / height * width)
# Изменяем размер
img.thumbnail((new_width, new_height))
# Сохраняем изображение
img = img.convert("RGB")
mobile_temp_file = io.BytesIO()
img.save(mobile_temp_file, format='JPEG')
getattr(instance, mobile_image_field).save(filename, mobile_temp_file, save=False)
else:
# Открываем изображение
img = Image.open(getattr(instance, image_field))
# Вычисляем новые размеры с сохранением пропорций
width, height = img.size
if width > height:
new_width = 400
new_height = int(400 / width * height)
else:
new_height = 400
new_width = int(400 / height * width)
# Изменяем размер
img.thumbnail((new_width, new_height))
# Сохраняем изображение
img = img.convert("RGB")
mobile_temp_file = io.BytesIO()
img.save(mobile_temp_file, format='JPEG')
getattr(instance, mobile_image_field).save(getattr(instance, image_field).name, mobile_temp_file, save=False)
Нужно, чтобы в else-блоке код срабатывал, только если фотка изменилась.
Пример работы:
class Country(models.Model):
name_in_cyrillic = models.CharField("Название странцы кириллицей", max_length=128)
name_in_latin = models.CharField("Название странцы латиницей", max_length=128)
flag = models.ImageField("Флаг", upload_to='flags', blank=True, null=True)
flag_url = models.CharField(max_length=128, null=True, blank=True, verbose_name='Прямая ссылка для картинки флага')
flag_mobile = models.ImageField("Флаг (мобильная версия)", upload_to='flags_mobile', blank=True, null=True)
def save(self, *args, **kwargs):
save_image_and_mobile(self, 'flag', 'flag_url', 'flag_mobile')
super().save(*args, **kwargs)
class Meta:
verbose_name = 'Страна'
verbose_name_plural = 'Страны'
def __str__(self):
return self.name_in_latin