如何使用DRF为Django Product模型实现多图上传并按产品名归档
实现产品多图上传并存储到同名文件夹的方案
1. 新增ProductImage模型
创建独立模型存储产品图片,通过外键关联Product,同时定义动态上传路径,确保图片存入产品同名文件夹:
from django.db import models from django.utils.text import slugify def product_image_upload_path(instance, filename): # 用slugify处理产品名称,避免特殊字符导致路径错误 product_folder = slugify(instance.product.name) return f'products/{product_folder}/{filename}' class ProductImage(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images') image = models.ImageField(upload_to=product_image_upload_path, null=True, blank=True) _id = models.AutoField(primary_key=True, editable=False)
related_name='images'方便后续从Product实例直接调用所有关联图片,slugify处理产品名称中的特殊字符,保证路径合法性。
2. 修改序列化器
添加嵌套的图片序列化器,让产品详情接口返回所有关联图片数据:
class ProductImageSerializer(serializers.ModelSerializer): class Meta: model = ProductImage fields = '__all__' class ProductSerializer(serializers.ModelSerializer): reviews = serializers.SerializerMethodField(read_only=True) images = ProductImageSerializer(many=True, read_only=True) # 新增图片字段 class Meta: model = Product fields = '__all__' def get_reviews(self, obj): reviews = obj.review_set.all() serializer = ReviewSerializer(reviews, many=True) return serializer.data
3. 处理多图上传的视图逻辑
新增创建产品的视图,支持接收多张图片并关联到对应产品:
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from .models import Product, ProductImage from .serializers import ProductSerializer @api_view(['POST']) @permission_classes([IsAuthenticated]) def createProduct(request): user = request.user data = request.data # 创建产品实例 product = Product.objects.create( user=user, name=data['name'], brand=data.get('brand', ''), category=data.get('category', ''), description=data.get('description', ''), price=data['price'], countInStock=data.get('countInStock', 0) ) # 处理批量上传的图片 images = request.FILES.getlist('images') for image in images: ProductImage.objects.create(product=product, image=image) serializer = ProductSerializer(product, many=False) return Response(serializer.data)
如果需要更新产品图片,可单独写视图处理:
@api_view(['PUT']) @permission_classes([IsAuthenticated]) def updateProductImages(request, pk): product = Product.objects.get(_id=pk) # 可选:删除原有图片(如需替换而非追加) # product.images.all().delete() images = request.FILES.getlist('images') for image in images: ProductImage.objects.create(product=product, image=image) serializer = ProductSerializer(product, many=False) return Response(serializer.data)
4. 配置媒体文件访问
在settings.py中配置媒体根目录和URL:
MEDIA_ROOT = BASE_DIR / 'media' MEDIA_URL = '/media/'
在项目根urls.py中添加媒体文件路由:
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 已有路由... ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
完成以上配置后,即可实现:
- 单产品关联多张图片
- 图片自动存入
media/products/[处理后的产品名称]/文件夹 - 获取产品详情时返回所有关联图片数据
内容的提问来源于stack exchange,提问作者chocpooh
相关产品推荐
相关产品推荐

