Django无表单多图上传问题:单图正常,多图无法接收需如何修改?
嘿,我来给你梳理两种实用的Django多图上传实现方案,都是基于你现有的代码改造的,你可以根据自己的场景选择:
方案一:一对多关联模型(通用推荐)
这个方案适配所有数据库类型,而且扩展性极强——以后要是想给单张图片加标题、排序权重、描述之类的字段,直接在子模型里加就行,非常灵活。
修改 models.py
把原来的单图字段拆分成两个关联模型:一个父模型Upload用来记录上传的基础信息,一个子模型Image用来存储单张图片,通过外键关联到Upload:
from django.db import models class Upload(models.Model): # 这里可以添加你需要的其他字段,比如上传时间、上传用户等 created_at = models.DateTimeField(auto_now_add=True) class Image(models.Model): upload = models.ForeignKey(Upload, on_delete=models.CASCADE, related_name='images') image = models.ImageField(upload_to='images/')
备注:
related_name='images'是为了方便从Upload实例直接获取所有关联的图片,比如upload.images.all()就能拿到该上传记录下的所有图片。
修改 serializers.py
需要用嵌套序列化器来处理关联模型的创建,同时重写create方法,手动拆分上传数据:
from rest_framework import serializers from .models import Upload, Image class ImageSerializer(serializers.ModelSerializer): class Meta: model = Image fields = ['image'] class UploadSerializer(serializers.ModelSerializer): images = ImageSerializer(many=True) class Meta: model = Upload fields = ['id', 'created_at', 'images'] def create(self, validated_data): # 先提取出图片相关的数据 images_data = validated_data.pop('images') # 创建父模型Upload的实例 upload = Upload.objects.create(**validated_data) # 循环创建每张图片对应的Image实例 for image_data in images_data: Image.objects.create(upload=upload, **image_data) return upload
修改 views.py
如果前端用FormData格式上传多文件(最常用的文件上传方式),可以重写create方法直接处理请求中的文件列表,这样前端不用传嵌套的JSON,只需把所有图片放在images字段里即可:
from rest_framework import viewsets, permissions from rest_framework.response import Response from .models import Upload, Image from .serializers import UploadSerializer class UploadViewSet(viewsets.ModelViewSet): queryset = Upload.objects.all() permission_classes = [permissions.AllowAny] serializer_class = UploadSerializer def create(self, request, *args, **kwargs): # 从请求中获取所有上传的图片文件 images = request.FILES.getlist('images') # 创建Upload实例 upload = Upload.objects.create() # 批量创建关联的Image实例 for img in images: Image.objects.create(upload=upload, image=img) # 返回序列化后的上传记录 serializer = self.get_serializer(upload) return Response(serializer.data, status=201)
方案二:使用ArrayField(仅适用于PostgreSQL数据库)
如果你的项目刚好使用PostgreSQL数据库,也可以用Django提供的ArrayField直接存储多个图片路径,代码改动更小,但扩展性较差(无法给单张图片加额外属性)。
修改 models.py
替换原来的ImageField为ArrayField:
from django.db import models from django.contrib.postgres.fields import ArrayField class Upload(models.Model): images = ArrayField(models.ImageField(upload_to='images/'), default=list)
修改 serializers.py
用ListField来处理多文件的序列化:
from rest_framework import serializers from .models import Upload class UploadSerializer(serializers.ModelSerializer): images = serializers.ListField( child=serializers.ImageField(max_length=100000, allow_empty_file=False, use_url=True) ) class Meta: model = Upload fields = '__all__'
修改 views.py
同样需要重写create方法来处理多文件上传:
from rest_framework import viewsets, permissions from .models import Upload from .serializers import UploadSerializer class UploadViewSet(viewsets.ModelViewSet): queryset = Upload.objects.all() permission_classes = [permissions.AllowAny] serializer_class = UploadSerializer def create(self, request, *args, **kwargs): images = request.FILES.getlist('images') upload = Upload.objects.create(images=images) serializer = self.get_serializer(upload) return Response(serializer.data, status=201)
内容的提问来源于stack exchange,提问作者Titan
相关产品推荐
相关产品推荐

