Saving programmatically an ImageField duplicates the image file
-
19-06-2021 - |
Question
I'm creating some instances of the Item
model shown below from a csv file. In the csv file only the name
and the filename
of the Item is specified. The image
field is set by looking if the image exists, and if it does, set the image file to image
:
I do:
item = Item()
item.name = csv_fields[0]
item.filename = csv_fields[1]
item.save()
...
f = open(settings.MEDIA_ROOT+"images/"+item.filename, 'r')
item.image = File(f)
item.save()
Doing so, the image is duplicated in settings.MEDIA_ROOT+"images/"
as <original filename>_1
. How can avoid that? i.e. how can I just set an existing file to an imagefield, without copying it?
class Item(models.Model):
name = models.CharField(max_length=50)
filename = models.CharField(max_length=100,)
image = models.ImageField(upload_to='images', blank=True, null=True)
Solution
This is all you need
item = Item()
item.name = csv_fields[0]
item.filename = csv_fields[1]
item.image = csv_fields[1]
item.save()
the image field takes a filename and the field definition's upload_to, and converts that to an image resource. if you pass in an image resource, it thinks its making a new one.
SO this:
f = open(settings.MEDIA_ROOT+"images/"+item.filename, 'r')
item.image = File(f)
isn't necessary at all
the only diff between a charfield and a image field is that a imagefield takes the filename and casts it to a PIL Image resource for further manipulation. its just a wrapper.
OTHER TIPS
Francis Yaconiello answer is correct, but I have one clarifying detail.
item.image = csv_fields[1]
Note that this should be a path relative to the media root or other storage root.
For example, say settings.MEDIA_ROOT = '/home/myuser/media'
and the ImageField(upload_to='images')
.
So if you manually save an image at `/home/myuser/media/images/purty.jpg', then csv_fields[1] should be:
item.image = '/images/purty.jpg'
Other wise, item.image.name, item.image.path, and item.image.url will be messed up.