Невозможно загрузить несколько изображений с помощью 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">