Here I am trying to update each product image of a particular product. But it is not working properly. Here only the image of first object is updating.
There is a template where we can update product and product images at once. ProductImage
has a ManyToOne
relation with Product
Model so in the template there can be multiple images objects of a single product.
Updating product model works fine but while updating ProductImage Objects it is not working.
Instead of zipping is there any other way to update multiple image objects at once ?
EDIT: If I unzip the images list then updating doesn't works properly. For example if I change the image of one object then the another object images changes. BUT when I change all the image objects images then the update works fine. It doesn't work properly when I change only some of the objects.
When I Zip then images list then this is the error traceback.
Traceback (most recent call last):
File "venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "venv\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "\venv\lib\site-packages\django\views\generic\base.py", line 73, in view
return self.dispatch(request, *args, **kwargs)
File "\venv\lib\site-packages\django\views\generic\base.py", line 101, in dispatch
return handler(request, *args, **kwargs)
File "dashboard\product\views\views.py", line 293, in post
p.save()
File "venv\lib\site-packages\django\db\models\base.py", line 751, in save
force_update=force_update, update_fields=update_fields)
File "venv\lib\site-packages\django\db\models\base.py", line 789, in save_base
force_update, using, update_fields,
File "venv\lib\site-packages\django\db\models\base.py", line 867, in _save_table
for f in non_pks]
File "lib\site-packages\django\db\models\base.py", line 867, in <listcomp>
for f in non_pks]
File "\venv\lib\site-packages\django\db\models\fields\files.py", line 303, in pre_save
if file and not file._committed:
AttributeError: 'tuple' object has no attribute '_committed'
models
class ProductImage(models.Model):
image = models.ImageField(upload_to='imgs',blank=True, null=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
template
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{product_form}}
<th>Current Image</th>
<th>Change</th>
{% for image in p_images %}
<tr><td>{{image.pk}}</td>
<td><img src="{{image.image.url}}" width="50" height="50"></td>
<td><input type="file" name="image"></td>
</tr>
{% endfor %}
<input type="submit">
views
def post(self, request, *args, **kwargs):
product = Product.objects.get(pk=kwargs['pk'])
product_form = ProductForm(request.POST, instance=product)
images = zip(request.FILES.getlist('image'))
p_images = ProductImage.objects.filter(product=product).order_by('pk')
if product_form.is_valid():
product_form.save()
# updating product images
for p, img in zip(p_images, images): # error is here
p.image = img
p.save()
# Tried this way too:
for img in images:
ProductImage.objects.filter(product=product).update(image=img)
First, change input
name
to be able to identify which ProductImage
was updated.
<!-- <td><input type="file" name="image"></td> -->
<td><input type="file" name="image-{{image.pk}}"></td>
Next, iterate the input_name
in request.FILES
and get the ProductImage
PK.
Then, lookup the ProductImage
p
, update the image
field and save
the model.
def post(self, request, *args, **kwargs):
product = Product.objects.get(pk=kwargs['pk'])
product_form = ProductForm(request.POST, instance=product)
if product_form.is_valid():
product_form.save()
# Updating product images
if request.FILES:
p_images = ProductImage.objects.filter(product=product).order_by('pk')
p_images_lookup = {p_image.pk: p_image for p_image in p_images}
for input_name in request.FILES:
p = p_images_lookup[int(input_name[len('image-'):])]
p.image = request.FILES[input_name]
p.save()
You’re unnecessarily zipping request.FILES.getlist(“images”)
leading to an array containing tuples, each containing an image object.
Change
images = zip(request.FILES.getlist('image'))
To
images = request.FILES.getlist('image')
Django request.FILES.getlist usage: https://docs.djangoproject.com/en/3.1/topics/http/file-uploads/#uploading-multiple-files
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With