-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfields.py
91 lines (75 loc) · 3.02 KB
/
fields.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import io
import os
from django.core.files import File
from django.core.exceptions import ValidationError
from django.db import models
from PIL import Image, ImageOps
class AdvanceThumbnailField(models.ImageField):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def contribute_to_class(self, cls, name, **kwargs):
super().contribute_to_class(cls, name, **kwargs)
models.signals.post_save.connect(self.convert_to_webp, sender=cls)
models.signals.pre_delete.connect(self.delete_image, sender=cls)
models.signals.pre_save.connect(self.auto_delete_file_on_change, sender=cls)
def pre_save(self, model_instance, add):
file = super().pre_save(model_instance, add)
if not file:
file.delete(save=False)
return file
def convert_to_webp(self, instance, **kwargs):
image_field = getattr(instance, self.name)
if not image_field or not image_field.name:
return
models.signals.post_save.disconnect(
self.convert_to_webp, sender=instance.__class__
)
try:
with image_field.open() as source_file:
img = Image.open(source_file)
img = ImageOps.exif_transpose(img)
webp_io = io.BytesIO()
img.save(webp_io, format="WEBP")
webp_io.seek(0)
base_name = os.path.basename(
image_field.name
)
name, _ = os.path.splitext(base_name)
name = f"{name}.webp"
image_field.delete(save=False)
webp_file = File(webp_io, name=name)
setattr(instance, self.name, webp_file)
instance.save(update_fields=[self.name])
finally:
models.signals.post_save.connect(
self.convert_to_webp, sender=instance.__class__
)
def delete_image(self, instance, **kwargs):
if instance.image:
image_path = instance.image.path
if os.path.exists(image_path):
os.remove(image_path)
else:
pass
def auto_delete_file_on_change(self, instance, **kwargs):
if not instance.pk:
return False
try:
old_instance = instance.__class__.objects.get(pk=instance.pk)
old_file = getattr(old_instance, self.name)
if not old_file:
return False
except instance.__class__.DoesNotExist:
return False
new_file = getattr(instance, self.name)
print(old_file.path, new_file.path)
if old_file and new_file and old_file != new_file:
old_file_path = old_file.path if old_file else None
new_file_path = new_file.path if new_file else None
if (
old_file_path
and old_file_path != new_file_path
and os.path.isfile(old_file_path)
):
os.remove(old_file_path)
return False