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

Django如何在Album的JSON响应中返回关联的图片列表

Django 一对多模型嵌套返回关联数据实现方案

你可以根据自己项目是否使用Django REST Framework(以下简称DRF,绝大多数Django接口项目的标配)选对应实现方式:

方式1:基于DRF实现(推荐)

核心是用嵌套序列化器处理关联的图片数据,步骤如下:

  1. 编写序列化器
    先写单张图片的序列化器,再在相册序列化器中嵌套图片列表字段,注意外键反向关联的默认命名规则:如果没给外键手动设置related_name,Django默认反向关联属性名为小写子表名_set,也就是这里的albumimage_set。
    from rest_framework import serializers
    from .models import Album, AlbumImage
    
    class AlbumImageSerializer(serializers.ModelSerializer):
        class Meta:
            model = AlbumImage
            # 按需调整要返回的图片字段
            fields = ['id', 'title', 'image']
    
    class AlbumSerializer(serializers.ModelSerializer):
        # 嵌套序列化多张图片,many=True表示是列表数据
        images = AlbumImageSerializer(many=True, read_only=True, source='albumimage_set')
        
        class Meta:
            model = Album
            fields = ['id', 'owner', 'title', 'images']
    
    小优化:如果不想每次写source参数,可以修改AlbumImage模型的外键字段,加related_name:
    # 把原来的album外键改成下面这样
    album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='images')
    
    改完后序列化器里的images字段可以去掉source参数,直接写images = AlbumImageSerializer(many=True, read_only=True)即可。
  2. 编写视图时预加载关联数据,避免N+1查询问题
    from rest_framework import generics
    from .models import Album
    from .serializers import AlbumSerializer
    
    class AlbumListApi(generics.ListAPIView):
        serializer_class = AlbumSerializer
        # prefetch_related一次性预加载所有关联图片,大幅减少数据库查询次数
        # 如果设置了related_name='images',括号里就改成'images'
        queryset = Album.objects.all().prefetch_related('albumimage_set')
    
    配置完路由后,接口返回的Album数据中就会自动携带images数组,包含该相册下所有图片的信息。

方式2:原生Django手写JsonResponse返回

如果项目没引入DRF,可以手动拼装JSON结构,同样记得做预加载优化:

from django.http import JsonResponse
from .models import Album

def album_list(request):
    # 预加载关联图片避免N+1
    album_list = Album.objects.all().prefetch_related('albumimage_set')
    result = []
    for album in album_list:
        # 遍历当前相册下的所有图片,拼装图片数据
        image_list = []
        for img in album.albumimage_set.all():
            image_list.append({
                "id": img.id,
                "title": img.title,
                # ImageField要取url属性才能拿到可访问的图片地址,空值时返回None
                "image": img.image.url if img.image else None
            })
        result.append({
            "id": album.id,
            "owner": album.owner_id,
            "title": album.title,
            "images": image_list
        })
    return JsonResponse(result, safe=False)

注意事项

  • 不管用哪种实现,查询Album数据时一定要加prefetch_related预加载关联图片,否则每处理一个相册就会单独发起一次数据库图片查询,数据量上来后接口响应会非常慢。
  • 返回ImageField字段时不要直接返回字段本身,要取image.url拿到可访问的资源路径,否则前端拿到的是文件对象的字符串表示,无法直接展示图片。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:36:47