You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中使用Subquery代码显示Amazon S3存储的图片?

问题原因

你当前通过Subquery直接提取photo字段值时,得到的是文件在S3中的相对路径字符串,而非Django的ImageFieldFile实例——只有这类实例才会自动拼接S3域名,生成可直接访问的完整URL。因此直接使用路径字符串无法加载图片,也不存在.photo或.url属性。

解决方案

方案一:数据库层面拼接完整URL(推荐)

通过数据库函数直接拼接MEDIA_URL和文件路径,在查询阶段就生成完整的S3访问地址:

  1. 导入必要依赖
from django.db.models import Value, Concat, Subquery, OuterRef
from django.conf import settings
from django.http import Http404
  1. 修改查询代码
try:
    user = MyUser.objects.get(pk=5)
except MyUser.DoesNotExist:
    raise Http404()

# 筛选优先级为1的ItemPhoto,仅取photo字段
photo_subqs = ItemPhoto.objects.filter(
    item=OuterRef('item'), 
    priority=1
).values('photo')

queryset = Order.objects.prefetch_related(
    Prefetch(
        'orderdetail_orderid', 
        queryset=OrderDetail.objects.select_related('order', 'item').annotate(
            # 拼接MEDIA_URL与photo路径,生成完整访问URL
            item_photo_url=Subquery(
                Concat(
                    Value(settings.MEDIA_URL),
                    photo_subqs.values('photo'),
                    output_field=models.CharField()
                )
            )
        ),
        to_attr='oor',
    ),
).filter(user=user).order_by('-created_at')
  1. 模板中直接使用
{% for order in orders %}
    {% for item in order.oor %}
        <img src="{{ item.item_photo_url }}">
    {% endfor %}
{% endfor %}

方案二:模板手动拼接MEDIA_URL

若不想修改查询逻辑,可在模板中手动拼接媒体域名前缀,前提是确保MEDIA_URL能在模板中访问:

  1. 确认模板上下文配置
    在settings.py的模板配置中,确保包含媒体上下文处理器:
TEMPLATES = [
    {
        # 其他配置项
        'OPTIONS': {
            'context_processors': [
                # 其他处理器
                'django.template.context_processors.media',
            ],
        },
    },
]
  1. 修改模板代码
{% for order in orders %}
    {% for item in order.oor %}
        <img src="{{ MEDIA_URL }}{{ item.item_photos }}">
    {% endfor %}
{% endfor %}

方案三:预取ItemPhoto实例(符合Django ORM习惯)

放弃Subquery,改用嵌套Prefetch直接获取ItemPhoto实例,直接调用实例的.photo.url属性:

  1. 修改查询代码
user = get_object_or_404(MyUser, pk=5)

# 预取每个Item下优先级为1的照片
photo_prefetch = Prefetch(
    'item__item_photo',
    queryset=ItemPhoto.objects.filter(priority=1),
    to_attr='priority_photos'
)

queryset = Order.objects.prefetch_related(
    Prefetch(
        'orderdetail_orderid', 
        queryset=OrderDetail.objects.select_related('order', 'item').prefetch_related(photo_prefetch),
        to_attr='oor',
    ),
).filter(user=user).order_by('-created_at')
  1. 模板中遍历使用
{% for order in orders %}
    {% for item in order.oor %}
        {% for photo in item.item.priority_photos %}
            <img src="{{ photo.photo.url }}">
        {% endfor %}
    {% endfor %}
{% endfor %}

内容的提问来源于stack exchange,提问作者K-Yuuma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:43:10