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

Django结合Fetch API动态加载图片:如何获取签名URL?

问题:Django动态加载商品时无法获取Linode对象存储的签名图片URL

在Django项目中,通过Fetch API根据选中分类动态加载商品,商品图片存储于Linode对象存储桶。使用模板标签{{product.image.url}}可正常显示带签名的完整URL,但前端JavaScript动态获取数据时,仅能拿到文件路径(如app/product/image),subproduct.image.url返回undefined。

前端代码

fetch(`opensubcategory/${id}`)
    .then(response => response.json())
    .then(data => {
        var subproducts = JSON.parse(data.products);
        for (var i = 0;i<subproducts.length;i++){
            var subproduct = subproducts[i].fields;
                let image = document.createElement('img');
                 console.log(subproduct.image)
                 imageurl = subproduct.image.url
                 image.src = imageurl;
                 image.classList.add("productimage");
                 imagediv.append(image);
        }
    })

后端代码

def opensubcategory(request,id):
    subcategory = Subcategory.objects.get(pk=id)
    subcategory_products = Product.objects.filter(subcategory=subcategory)

    products_serialized = serialize("json",subcategory_products)

    return JsonResponse({"products":products_serialized})

解决方案

问题根源在于:Django内置的serialize函数仅序列化模型的数据库原始字段值,而image.url是FileField实例的动态属性(并非数据库存储内容),因此不会被自动包含在序列化结果中。模板标签{{product.image.url}}是在服务器渲染时调用了该属性,才生成签名URL。

方法1:手动在视图中添加签名URL

直接在后端循环处理每个商品,将image.url的结果添加到返回数据中:

def opensubcategory(request, id):
    subcategory = Subcategory.objects.get(pk=id)
    subcategory_products = Product.objects.filter(subcategory=subcategory)
    
    # 手动构建包含签名URL的商品数据
    products_data = []
    for product in subcategory_products:
        product_info = {
            # 序列化所有模型字段
            **{field.name: getattr(product, field.name) for field in product._meta.fields},
            # 添加上签名后的图片URL
            'image_url': product.image.url if product.image else ''
        }
        products_data.append(product_info)
    
    return JsonResponse({"products": products_data})

前端对应修改(无需再JSON.parse):

fetch(`opensubcategory/${id}`)
    .then(response => response.json())
    .then(data => {
        var subproducts = data.products;
        for (var i = 0; i < subproducts.length; i++){
            var subproduct = subproducts[i];
            let image = document.createElement('img');
            image.src = subproduct.image_url;
            image.classList.add("productimage");
            imagediv.append(image);
        }
    })

方法2:使用Django REST Framework序列化器(推荐,若项目已用DRF)

定义自定义序列化器,主动处理image.url属性:

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    # 自定义字段获取签名URL
    image_url = serializers.SerializerMethodField()

    class Meta:
        model = Product
        fields = '__all__'  # 或指定需要的字段,需包含image_url

    def get_image_url(self, obj):
        return obj.image.url if obj.image else ''

视图中使用该序列化器:

from .serializers import ProductSerializer

def opensubcategory(request, id):
    subcategory = Subcategory.objects.get(pk=id)
    subcategory_products = Product.objects.filter(subcategory=subcategory)
    serializer = ProductSerializer(subcategory_products, many=True)
    return JsonResponse({"products": serializer.data})

前端代码同方法1,直接使用subproduct.image_url即可。


内容的提问来源于stack exchange,提问作者Elina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:35:36