Django项目中如何用Python遍历AWS S3中的图片对象?
解决AWS S3环境下无法遍历媒体文件夹图片的问题
问题根源
本地环境用os.listdir()读取本地文件系统的媒体文件夹是可行的,但生产环境中媒体文件存储在AWS S3上,os.listdir()无法访问远程S3存储,因此失效。需要改用AWS S3的API来获取指定前缀(对应文件夹)下的文件列表。
解决方案1:使用Django默认存储类(推荐,适配django-storages)
如果你的项目已经配置了django-storages来对接S3,直接用Django的default_storage即可完成文件列表遍历,无需直接操作boto3:
修改视图代码
from django.conf import settings from django.shortcuts import get_object_or_404, render from urllib.parse import quote from django.core.files.storage import default_storage def carmodel(request, carmodel_id): carmodel = get_object_or_404(CarModel, id=carmodel_id) # S3中对应"文件夹"的前缀(S3无真实文件夹,靠对象键前缀区分) s3_prefix = f"{carmodel.title}/" # 用default_storage列出前缀下的文件:listdir返回(子文件夹列表, 文件列表) _, image_files = default_storage.listdir(s3_prefix) # 编码文件夹名中的特殊字符(如空格),用于构建URL encoded_folder_name = quote(carmodel.title) # 取出配置好的MEDIA_URL,确保末尾无斜杠 media_base_url = settings.MEDIA_URL.rstrip('/') return render(request, 'vehicles/vehicle.html', { "carmodel": carmodel, "image_folder": image_files, "folder_name": encoded_folder_name, "media_url": media_base_url })
修改模板代码
{% for image in image_folder %} <img src="{{ media_url }}/{{ folder_name }}/{{ image }}" class="slider-thumbnail"> {% endfor %}
解决方案2:直接使用boto3操作S3
如果未使用django-storages,可以直接用boto3调用S3 API:
1. 安装依赖
pip install boto3
2. 修改视图代码
import boto3 from django.conf import settings from django.shortcuts import get_object_or_404, render from urllib.parse import quote def carmodel(request, carmodel_id): carmodel = get_object_or_404(CarModel, id=carmodel_id) s3_prefix = f"{carmodel.title}/" # 初始化S3客户端 s3_client = boto3.client( 's3', aws_access_key_id=settings.AWS_ACCESS_KEY_ID, aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY, region_name=settings.AWS_S3_REGION_NAME ) # 列出指定前缀下的对象 response = s3_client.list_objects_v2( Bucket=settings.AWS_STORAGE_BUCKET_NAME, Prefix=s3_prefix ) image_files = [] if 'Contents' in response: for obj in response['Contents']: # 提取文件名(去掉前缀部分),跳过空的"文件夹"对象 file_name = obj['Key'].replace(s3_prefix, '', 1) if file_name: image_files.append(file_name) encoded_folder_name = quote(carmodel.title) media_base_url = settings.MEDIA_URL.rstrip('/') return render(request, 'vehicles/vehicle.html', { "carmodel": carmodel, "image_folder": image_files, "folder_name": encoded_folder_name, "media_url": media_base_url })
模板代码同方案1
注意事项
- 确保AWS IAM角色/用户拥有S3存储桶的
ListBucket和GetObject权限,否则无法读取文件列表和访问图片。 - 检查Django配置中的S3参数:
AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_S3_REGION_NAME、AWS_STORAGE_BUCKET_NAME必须正确配置。 - 如果前缀下的文件超过1000个,需要处理S3的分页查询(通过
ContinuationToken循环获取所有对象),上述示例代码为简化版,仅处理单次返回的结果。
内容的提问来源于stack exchange,提问作者Luca
相关产品推荐
相关产品推荐

