Django如何在Album的JSON响应中返回关联的图片列表
Django 一对多模型嵌套返回关联数据实现方案
你可以根据自己项目是否使用Django REST Framework(以下简称DRF,绝大多数Django接口项目的标配)选对应实现方式:
方式1:基于DRF实现(推荐)
核心是用嵌套序列化器处理关联的图片数据,步骤如下:
- 编写序列化器
先写单张图片的序列化器,再在相册序列化器中嵌套图片列表字段,注意外键反向关联的默认命名规则:如果没给外键手动设置related_name,Django默认反向关联属性名为小写子表名_set,也就是这里的albumimage_set。
小优化:如果不想每次写source参数,可以修改AlbumImage模型的外键字段,加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']related_name:
改完后序列化器里的images字段可以去掉source参数,直接写# 把原来的album外键改成下面这样 album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='images')images = AlbumImageSerializer(many=True, read_only=True)即可。 - 编写视图时预加载关联数据,避免N+1查询问题
配置完路由后,接口返回的Album数据中就会自动携带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')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
相关产品推荐
相关产品推荐

