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

如何使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:50:37