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
相关产品推荐
相关产品推荐

