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

如何在Django电商项目中实现商品多图展示功能

Django电商商品多图展示实现方案

1. 模型设计

创建关联的商品主模型和图片模型,通过外键绑定,同时添加主图标记字段保证每个商品仅一个主图:

# models.py
from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    # 补充其他商品字段(如描述、分类、库存等)

    def __str__(self):
        return self.name

class ProductImage(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='images')
    image = models.ImageField(upload_to='products/')
    is_main = models.BooleanField(default=False)
    alt_text = models.CharField(max_length=255, blank=True)  # 用于SEO的图片替代文本

    def save(self, *args, **kwargs):
        # 自动取消同商品其他图片的主图标记
        if self.is_main:
            ProductImage.objects.filter(product=self.product, is_main=True).exclude(pk=self.pk).update(is_main=False)
        super().save(*args, **kwargs)

    def __str__(self):
        return f"{self.product.name} - {'主图' if self.is_main else '副图'}"

2. 媒体文件配置

确保项目能正确处理图片上传和访问:

# settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'

在项目根路由中添加媒体文件访问路由:

# project/urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('your_app.urls')),  # 替换为你的应用路由
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

3. 视图逻辑实现

在商品详情视图中,区分主图和其他图片并传递给模板:

# views.py
from django.shortcuts import get_object_or_404, render
from .models import Product

def product_detail(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    # 获取主图,无主图则取第一张图
    main_image = product.images.filter(is_main=True).first() or product.images.first()
    # 获取除主图外的其他图片
    other_images = product.images.exclude(pk=main_image.pk) if main_image else product.images.all()
    
    context = {
        'product': product,
        'main_image': main_image,
        'other_images': other_images,
    }
    return render(request, 'product_detail.html', context)

4. 模板渲染与交互

参考亚马逊布局,实现主图+缩略图切换的效果:

<!-- templates/product_detail.html -->
<div class="product-gallery">
    <!-- 主图展示区 -->
    <div class="main-image-box">
        {% if main_image %}
            <img id="main-product-img" src="{{ main_image.image.url }}" alt="{{ main_image.alt_text|default:product.name }}">
        {% else %}
            <img id="main-product-img" src="/media/default-product.png" alt="默认商品图">
        {% endif %}
    </div>

    <!-- 缩略图切换区 -->
    <div class="thumbnail-box">
        {% for img in other_images %}
            <img class="thumbnail" src="{{ img.image.url }}" alt="{{ img.alt_text|default:product.name }}" onclick="switchMainImage('{{ img.image.url }}')">
        {% endfor %}
        {% if main_image and not other_images %}
            <img class="thumbnail active" src="{{ main_image.image.url }}" alt="{{ main_image.alt_text|default:product.name }}">
        {% endif %}
    </div>
</div>

<script>
// 切换主图的函数
function switchMainImage(imgUrl) {
    document.getElementById('main-product-img').src = imgUrl;
    // 给选中的缩略图添加激活样式
    document.querySelectorAll('.thumbnail').forEach(item => item.classList.remove('active'));
    event.target.classList.add('active');
}
</script>

<!-- 商品基础信息 -->
<h1>{{ product.name }}</h1>
<p>售价: ¥{{ product.price }}</p>
<!-- 其他商品详情内容 -->

配合CSS美化布局(可选):

.product-gallery {
    display: flex;
    gap: 20px;
    margin: 20px 0;
}

.main-image-box img {
    width: 450px;
    height: auto;
    object-fit: contain;
}

.thumbnail-box {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.thumbnail {
    width: 80px;
    height: 80px;
    object-fit: cover;
    cursor: pointer;
    border: 2px solid transparent;
}

.thumbnail.active {
    border-color: #007185;
}

5. 后台管理优化

在Django Admin中关联商品和图片,方便批量管理:

# admin.py
from django.contrib import admin
from .models import Product, ProductImage

class ProductImageInline(admin.TabularInline):
    model = ProductImage
    extra = 1  # 默认显示1个额外的图片上传框

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    inlines = [ProductImageInline]
    list_display = ('name', 'price')

@admin.register(ProductImage)
class ProductImageAdmin(admin.ModelAdmin):
    list_display = ('product', 'is_main', 'alt_text')
    list_filter = ('is_main',)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 12:45:33