Tạo models Thư viện hình ảnh cho sản phẩm trong Django

Thư viện hình ảnh (Image Gallery) sản phẩm tức là: Một sản phẩm sẽ có nhiều hình ảnh.

Đây là khai báo trong tệp models.py

# models.py

class Product(models.Model): 
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True)
    # ...

    def __str__(self):
        return self.title

class ProductImage(models.Model):
    # Thêm khóa ngoại tới sản phẩm
    product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="product_image")
    image = models.ImageField( upload_to="product_images/", default="media/no_image.jpg")
    alt_text = models.CharField(max_length=255, null=True, blank=True)
 
    def __str__(self):
        return self.product.title

Trong tệp trên, lưu ý related_name="product_image", trong đó product_image sẽ được sử dụng trong templates.

Khai báo tệp views.py

# views.py
def product_detail(request, slug):
    product = Product.objects.get(slug=slug)

    return render(request, 'product_detail.html', {
        "product": product,
    })

Khai báo tệp admin.py

#  admin.py
class ProductAdmin(admin.ModelAdmin):
    list_display = ("title", "slug")  
    #...

    inlines = [
        ProductImageInline,
    ]
admin.site.register(Product, ProductAdmin)

class ProductImageInline(admin.TabularInline):
    model = ProductImage

Hình ảnh được tích hợp vào trong tab sản phẩm để thuận tiện hơn khi đăng/sửa.

Sử dụng trong templates

{# product_detail.html #} 

{# Hiển thị tất cả hình ảnh (gallery) #}
<div id="image-gallery">
    {% for img in product.product_image.all %}
    <img src="{{ img.image.url }}" data-src="{{ img.image.url }}" alt="">
    {% endfor %}
</div>

{# Hiển thị 1 hình ảnh đầu tiên (gallery) #}
<img src="{{ product.product_image.all.0.image.url }}" alt="">
Lưu ý cho hình ảnh được nhập từ scrapy. Bỏ qua nếu hình ảnh của bạn là tự tải lên

Trong tệp templates, nếu trường hình ảnh của bạn là hình ảnh liên kết bên ngoài (ví dụ như được lưu từ scrapy) thì xóa .url

Để thuận tiện hơn khi đăng sản phẩm và hình ảnh.