Невозможно загрузить несколько изображений с помощью django

Я пытаюсь создать страницу для добавления нового товара с его изображениями в другую модель на моем сайте, используя Djnago. Длина получаемого списка изображений всегда равна 0 и я получаю IndexError: list index out of range. Я предполагаю, что я получаю файлы из запроса неправильно, используя images = request.FILES.getlist('images')

models.py

class Products(models.Model):
    product_name = models.CharField(
        max_length=255, verbose_name='Product name')
    product_slug = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    product_image = models.ImageField(
        default='image-placeholder.png', verbose_name='Image')
    creaton_date = models.DateTimeField(auto_now_add=True)
    brand = models.ForeignKey(
        Brands, verbose_name='Brand', on_delete=models.PROTECT)
    price = models.FloatField(verbose_name='Price')
    description = models.TextField(null=True, verbose_name='Description')
    category = models.ForeignKey(
        Categories, on_delete=models.CASCADE, verbose_name='Category')
    bought_count = models.IntegerField(null=True, default=0)

template.html

<form id="checkoutform" action="" method="post">
{% csrf_token %}
<div class="caption">
    <div class="form-group">
        <input class="input" type="text" name="product-name" placeholder="Product name">
    </div>
    <div class="form-group">
        <input class="input" type="text" name="brand" placeholder="Brand">
    </div>
    <div class="form-group">
        <input class="input" type="number" name="price" placeholder="Price">
    </div>
    <div class="form-group">
        <input class="input" type="file" multiple name="images" placeholder="Images">
    </div>
    <div class="form-group">
        <input class="input" type="text" name="desc" placeholder="Description">
    </div>
    <div class="form-group">
        <input class="input" type="text" name="category" placeholder="Category">
    </div>
    <input type="submit" value="Submit">
</form>

views.py

def create_product(request):
    if request.user.is_superuser:
        if request.method == 'POST':
            data = request.POST
            images = request.FILES.getlist('images')
            brand = Brands.objects.get(name=data['brand'])
            category =  Categories.objects.get(name=data['category'])
            product = Products.objects.create(
                product_name = data['product-name'],
                brand=brand,
                price = data['price'],
                description = data['desc'],
                category = category,
                image = images[0],
            )
            for i in range (1, len(images)):
                image = ProductImage.objects.create(
                    product = product,
                    image = images[i]
            )

        return render(request, 'store/create_product.html')
    else:
        return HttpResponse("You are not allowed here")

Хорошо, если вы не возражаете, я собираюсь предложить другой способ загрузки нескольких изображений, сначала создав отдельную модель для обработки изображений, а также форму для обработки загрузки нескольких изображений.

Models.py 

 class Products(models.Model):
    product_name = models.CharField(
        max_length=255, verbose_name='Product name')
    product_slug = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
    product_image = models.ImageField(
        default='image-placeholder.png', verbose_name='Image')
    creaton_date = models.DateTimeField(auto_now_add=True)
    brand = models.ForeignKey(
        Brands, verbose_name='Brand', on_delete=models.PROTECT)
    price = models.FloatField(verbose_name='Price')
    description = models.TextField(null=True, verbose_name='Description')
    category = models.ForeignKey(
        Categories, on_delete=models.CASCADE, verbose_name='Category')
    bought_count = models.IntegerField(null=True, default=0)


class productImage(models.Model):
      product = models.ForeignKey(Product,on_delete=models.CASCADE)
      image = models.ImageField(default='image-placeholder.png', verbose_name='Image')

Вам придется связать две модели вместе в админке с помощью StackedInine, например, так:

Admin.py

from .models import Products,ProductImage


class ProductAdminImage(Admin.StackedInline)
      model = ProductImage

@Admin.register(Products)
class ProductAdmin(Admin.ModelAdmin):
      list_display = [] # fields that you want to display 
      inlines = [ProductAdminImage] # Here we are linking both models with an inline 

Теперь мы будем работать над forms.py для обработки загрузки нескольких изображений

from .models import ProductImage 

class ProductImageForm(forms.ModelForm):
      class Meta:
            model = ProductImage 
            fields = ['image']
            widgets ={'image' :forms.ClearableFileInput(attrs={'multiple':True})}
            

Наконец, мы сосредоточимся на представлении для манипулирования загрузками для наших изображений, то, что вы сделали до сих пор, хорошо, но есть другой способ загрузки нескольких изображений, это сработало для меня во многих случаях!

from .forms import ProductImageForm

def create_product(request):
    if request.user.is_superuser:
        if request.method == 'POST':
            data = request.POST
            images = request.FILES.getlist('images')
            brand = Brands.objects.get(name=data['brand'])
            category =  Categories.objects.get(name=data['category'])
            form = ProductImageForm(request.POST, request.FILES)
            product = Products(product_name = data['product-name'],brand=brand,
                price = data['price'],
                description = data['desc'],
                category = category,
                product_image = images[0],)
            product.save()
            if form.is_valid():
               data = form.save(commit=False)
               for files in images:
                   data =ProductImage(product = product, image = files)
                   data.save()
                   return render(request, 'store/create_product.html')
            else:
                   return HttpResponse("You are not allowed here")

Для тех, кто, возможно, сталкивался с подобной проблемой, решение было невероятно очевидным. Я просто забыл добавить enctype="multipart/form-data" к своей форме (для загрузки медиафайлов)

<form id="checkoutform" action="" method="post" enctype="multipart/form-data">
Вернуться на верх