如何在Django中获取S3存储的图片宽高并存储至对应Model
实现方案
第一步:安装依赖
需要用到Pillow处理图片,requests获取S3图片流:
pip install pillow requests
第二步:修改模型代码,重写save方法
在原有Image模型中新增自动计算宽高的逻辑,默认仅新增实例时计算,避免不必要的性能损耗,你也可以自行补充字段变更判断逻辑实现更新图片时重新计算:
from django.db import models import requests from io import BytesIO from PIL import Image as PILImage from .project_model import Project class Image(models.Model): image = models.TextField(blank=False) image_width = models.IntegerField(default=0) image_height = models.IntegerField(default=0) project_id = models.ForeignKey(Project, on_delete=models.CASCADE) is_thumpnail = models.BooleanField(blank=False) upload_on = models.DateTimeField("created on", auto_now_add=True) updated_on = models.DateTimeField("updated on", auto_now=True) def save(self, *args, **kwargs): # 新增实例时计算宽高,如需更新图片时重新计算可自行补充字段变更判断 if not self.pk: try: # 从S3获取图片流 response = requests.get(self.image, timeout=10) response.raise_for_status() # 读取图片尺寸 with PILImage.open(BytesIO(response.content)) as img: self.image_width, self.image_height = img.size except Exception as e: # 异常情况保留默认值,可根据需求调整错误处理逻辑 pass super().save(*args, **kwargs) def __str__(self): # 原代码返回不存在的file_name字段,这里修正为返回图片URL return self.image
注意:如果你的S3桶是私有权限,不能直接通过URL访问,可替换请求逻辑为用boto3直接从S3下载文件到内存再解析,无需公网访问。
第三步:接口返回适配(对应你给出的返回示例)
如果你用DRF做接口,直接在序列化器中新增对应字段映射即可:
from rest_framework import serializers from .models import Image class ImageSerializer(serializers.ModelSerializer): width = serializers.IntegerField(source='image_width') height = serializers.IntegerField(source='image_height') link = serializers.CharField(source='image') class Meta: model = Image fields = ['id', 'width', 'height', 'link', 'upload_on'] # 按需补充其他返回字段
完成上述修改后,每次保存Image实例时会自动拉取S3的图片计算宽高存入对应字段,接口返回也能适配你给出的示例格式。
内容的提问来源于stack exchange,提问作者Kwall
相关产品推荐
相关产品推荐

