无法使用django上传多张图片

Cant upload multilple images using 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)


class ProductImage(models.Model):
    product = models.ForeignKey(Products, on_delete=models.CASCADE)
    image = models.ImageField()
    default = models.BooleanField(default=False)

    def __str__(self):
        return str(self.product)

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')

您必须 link 在管理员中使用 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">