Django ImageField 使用及其性能问题
Djnago 自带的 ImageField 对处理图片非常实用。
- ImageField 可以接受两个参数
width_field
和height_field
。 - 每当 ImageField 更新,会自动更新
height
和width
信息
from django.db import models
class Photo(models.Model):
image = models.ImageField(
blank=True,
null=True,
height_field="height",
width_field="width",
)
height = models.PositiveIntegerField(default=0)
width = models.PositiveIntegerField(default=0)
有了这些信息,就可以对图片大小排序,过滤操作。
from django.db.models import Q
big_dim = 1024;
big_images = Photo.objects.filter(
Q(height=big_dim) | Q(width=big_dim)
)
缺点:
- 增加图片
width
和height
信息每次查询都会把图片数据读到内存。 - 如果是用的是 s3 类似的存储方式会对性能造成巨大伤害
解决方法:
- 删除原本 Photo 字段中
width_field
和height_field
- 利用 Django Singals 的
pre_save
在存储图片前设置图片大小
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
class Photo(models.Model):
image = models.ImageField(
blank=True,
null=True,
)
height = models.PositiveIntegerField(blank=True, null=True)
width = models.PositiveIntegerField(blank=True, null=True)
@receiver(pre_save, sender=Photo)
def set_photo_dim(sender, instance: Photo, raw, **kwargs):
if isinstance(instance, sender):
setattr(instance, "width", instance.file.width)
setattr(instance, "height", instance.file.height)