199π
I have some code that fetches an image off the web and stores it in a model. The important bits are:
from django.core.files import File # you need this somewhere
import urllib
# The following actually resides in a method of my model
result = urllib.urlretrieve(image_url) # image_url is a URL to an image
# self.photo is the ImageField
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
Thatβs a bit confusing because itβs pulled out of my model and a bit out of context, but the important parts are:
- The image pulled from the web is not stored in the upload_to folder, it is instead stored as a tempfile by urllib.urlretrieve() and later discarded.
- The ImageField.save() method takes a filename (the os.path.basename bit) and a django.core.files.File object.
Let me know if you have questions or need clarification.
Edit: for the sake of clarity, here is the model (minus any required import statements):
class CachedImage(models.Model):
url = models.CharField(max_length=255, unique=True)
photo = models.ImageField(upload_to=photo_path, blank=True)
def cache(self):
"""Store image locally if we have a URL"""
if self.url and not self.photo:
result = urllib.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
130π
Super easy if model hasnβt been created yet:
First, copy your image file to the upload path (assumed = βpath/β in following snippet).
Second, use something like:
class Layout(models.Model):
image = models.ImageField('img', upload_to='path/')
layout = Layout()
layout.image = "path/image.png"
layout.save()
tested and working in django 1.4, it might work also for an existing model.
- [Django]-Python (and Django) best import practices
- [Django]-How do I remove Label text in Django generated form?
- [Django]-Pulling data to the template from an external database with django
43π
Just a little remark. tvon answer works but, if youβre working on windows, you probably want to open()
the file with 'rb'
. Like this:
class CachedImage(models.Model):
url = models.CharField(max_length=255, unique=True)
photo = models.ImageField(upload_to=photo_path, blank=True)
def cache(self):
"""Store image locally if we have a URL"""
if self.url and not self.photo:
result = urllib.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
or youβll get your file truncated at the first 0x1A
byte.
- [Django]-How do I run tests for all my Django apps only?
- [Django]-What's the best solution for OpenID with Django?
- [Django]-Row level permissions in django
19π
Ok, If all you need to do is associate the already existing image file path with the ImageField, then this solution may be helpfull:
from django.core.files.base import ContentFile
with open('/path/to/already/existing/file') as f:
data = f.read()
# obj.image is the ImageField
obj.image.save('imgfilename.jpg', ContentFile(data))
Well, if be earnest, the already existing image file will not be associated with the ImageField, but the copy of this file will be created in upload_to dir as βimgfilename.jpgβ and will be associated with the ImageField.
- [Django]-How to delete a record in Django models?
- [Django]-Celery : Execute task after a specific time gap
- [Django]-*_set attributes on Django Models
18π
Here is a method that works well and allows you to convert the file to a certain format as well (to avoid βcannot write mode P as JPEGβ error):
import urllib2
from django.core.files.base import ContentFile
from PIL import Image
from StringIO import StringIO
def download_image(name, image, url):
input_file = StringIO(urllib2.urlopen(url).read())
output_file = StringIO()
img = Image.open(input_file)
if img.mode != "RGB":
img = img.convert("RGB")
img.save(output_file, "JPEG")
image.save(name+".jpg", ContentFile(output_file.getvalue()), save=False)
where image is the django ImageField or your_model_instance.image
here is a usage example:
p = ProfilePhoto(user=user)
download_image(str(user.id), p.image, image_url)
p.save()
Hope this helps
- [Django]-Django's Double Underscore
- [Django]-Python Asyncio in Django View
- [Django]-Cron and virtualenv
13π
A lot of these answers were outdated, and I spent many hours in frustration (Iβm fairly new to Django & web dev in general). However, I found this excellent gist by @iambibhas: https://gist.github.com/iambibhas/5051911
import requests
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
def save_image_from_url(model, url):
r = requests.get(url)
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(r.content)
img_temp.flush()
model.image.save("image.jpg", File(img_temp), save=True)
- [Django]-How to solve "Page not found (404)" error in Django?
- [Django]-Stack trace from manage.py runserver not appearing
- [Django]-How do Django models work?
12π
Another possible way to do that:
from django.core.files import File
with open('path_to_file', 'r') as f: # use 'rb' mode for python3
data = File(f)
model.image.save('filename', data, True)
- [Django]-How does the get_or_create function in Django return two values?
- [Django]-Parsing unicode input using python json.loads
- [Django]-Is this the right way to do dependency injection in Django?
11π
What I did was to create my own storage that will just not save the file to the disk:
from django.core.files.storage import FileSystemStorage
class CustomStorage(FileSystemStorage):
def _open(self, name, mode='rb'):
return File(open(self.path(name), mode))
def _save(self, name, content):
# here, you should implement how the file is to be saved
# like on other machines or something, and return the name of the file.
# In our case, we just return the name, and disable any kind of save
return name
def get_available_name(self, name):
return name
Then, in my models, for my ImageField, Iβve used the new custom storage:
from custom_storage import CustomStorage
custom_store = CustomStorage()
class Image(models.Model):
thumb = models.ImageField(storage=custom_store, upload_to='/some/path')
- [Django]-Django: list all reverse relations of a model
- [Django]-Django proxy model and ForeignKey
- [Django]-How to convert JSON data into a Python object?
7π
If you want to just βsetβ the actual filename, without incurring the overhead of loading and re-saving the file (!!), or resorting to using a charfield (!!!), you might want to try something like this β
model_instance.myfile = model_instance.myfile.field.attr_class(model_instance, model_instance.myfile.field, 'my-filename.jpg')
This will light up your model_instance.myfile.url and all the rest of them just as if youβd actually uploaded the file.
Like @t-stone says, what we really want, is to be able to set instance.myfile.path = βmy-filename.jpgβ, but Django doesnβt currently support that.
- [Django]-Django model CharField: max_length does not work?
- [Django]-Django gives Bad Request (400) when DEBUG = False
- [Django]-How do you configure Django to send mail through Postfix?
2π
This is might not be the answer you are looking for. but you can use charfield to store the path of the file instead of ImageFile. In that way you can programmatically associate uploaded image to field without recreating the file.
- [Django]-IOS app with Django
- [Django]-How can I chain Django's "in" and "iexact" queryset field lookups?
- [Django]-Django models: Only permit one entry in a model?
2π
With Django 3,
with a model such as this one:
class Item(models.Model):
name = models.CharField(max_length=255, unique=True)
photo= models.ImageField(upload_to='image_folder/', blank=True)
if the image has already been uploaded, we can directly do :
Item.objects.filter(...).update(photo='image_folder/sample_photo.png')
or
my_item = Item.objects.get(id=5)
my_item.photo='image_folder/sample_photo.png'
my_item.save()
- [Django]-Add inline model to django admin site
- [Django]-Django set default form values
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-How do I create a slug in Django?
- [Django]-Django: Arbitrary number of unnamed urls.py parameters
- [Django]-Django :How to integrate Django Rest framework in an existing application?
1π
class tweet_photos(models.Model):
upload_path='absolute path'
image=models.ImageField(upload_to=upload_path)
image_url = models.URLField(null=True, blank=True)
def save(self, *args, **kwargs):
if self.image_url:
import urllib, os
from urlparse import urlparse
file_save_dir = self.upload_path
filename = urlparse(self.image_url).path.split('/')[-1]
urllib.urlretrieve(self.image_url, os.path.join(file_save_dir, filename))
self.image = os.path.join(file_save_dir, filename)
self.image_url = ''
super(tweet_photos, self).save()
- [Django]-Django url tag multiple parameters
- [Django]-TransactionManagementError "You can't execute queries until the end of the 'atomic' block" while using signals, but only during Unit Testing
- [Django]-Django: Reference to an outer query may only be used in a subquery
1π
class Pin(models.Model):
"""Pin Class"""
image_link = models.CharField(max_length=255, null=True, blank=True)
image = models.ImageField(upload_to='images/', blank=True)
title = models.CharField(max_length=255, null=True, blank=True)
source_name = models.CharField(max_length=255, null=True, blank=True)
source_link = models.CharField(max_length=255, null=True, blank=True)
description = models.TextField(null=True, blank=True)
tags = models.ForeignKey(Tag, blank=True, null=True)
def __unicode__(self):
"""Unicode class."""
return unicode(self.image_link)
def save(self, *args, **kwargs):
"""Store image locally if we have a URL"""
if self.image_link and not self.image:
result = urllib.urlretrieve(self.image_link)
self.image.save(os.path.basename(self.image_link), File(open(result[0], 'r')))
self.save()
super(Pin, self).save()
- [Django]-Django return file over HttpResponse β file is not served correctly
- [Django]-How do you use the django-filter package with a list of parameters?
- [Django]-Django-nonrel + Django-registration problem: unexpected keyword argument 'uidb36' when resetting password
1π
Working!
You can save image by using FileSystemStorage.
check the example below
def upload_pic(request):
if request.method == 'POST' and request.FILES['photo']:
photo = request.FILES['photo']
name = request.FILES['photo'].name
fs = FileSystemStorage()
##### you can update file saving location too by adding line below #####
fs.base_location = fs.base_location+'/company_coverphotos'
##################
filename = fs.save(name, photo)
uploaded_file_url = fs.url(filename)+'/company_coverphotos'
Profile.objects.filter(user=request.user).update(photo=photo)
- [Django]-AccessDenied when calling the CreateMultipartUpload operation in Django using django-storages and boto3
- [Django]-TransactionManagementError "You can't execute queries until the end of the 'atomic' block" while using signals, but only during Unit Testing
- [Django]-Pulling data to the template from an external database with django
0π
class DemoImage(models.Model):
title = models.TextField(max_length=255, blank=False)
image = models.ImageField(blank=False, upload_to="images/DemoImages/")
import requests
import urllib.request
from django.core.files import File
url = "https://path/to/logo.jpg"
# Below 3 lines is to fake as browser agent
# as many sites block urllib class suspecting to be bots
opener = urllib.request.build_opener()
opener.addheaders = [("User-agent", "Mozilla/5.0")]
urllib.request.install_opener(opener)
# Issue command to actually download and create temp img file in memory
result = urllib.request.urlretrieve(url)
# DemoImage.objects.create(title="title", image=File(open(result[0], "rb")))
# ^^ This erroneously results in creating the file like
# images/DemoImages/path/to/temp/dir/logo_image_file
# as opposed to
# images/DemoImages/logo_image_file
# Solution to get the file in images/DemoImages/
reopen = open(result[0], "rb") # Returns a BufferedReader object of the temp image
django_file = File(reopen) # Create the file from the BufferedReader object
demoimg = DemoImage()
demoimg.title = "title"
demoimg.image.save("logo.png", django_file, save=True)
This approach also triggers file upload to cloudinary/S3 if so configured
- [Django]-How to use Django ImageField, and why use it at all?
- [Django]-Django.contrib.auth.logout in Django
- [Django]-South migration: "database backend does not accept 0 as a value for AutoField" (mysql)
0π
So, if you have a model with an imagefield with an upload_to attribute set, such as:
class Avatar(models.Model):
image_file = models.ImageField(upload_to=user_directory_path_avatar)
then it is reasonably easy to change the image, at least in django 3.15.
In the view, when you process the image, you can obtain the image from:
self.request.FILES['avatar']
which is an instance of type InMemoryUploadedFile, as long as your html form has the enctype set and a field for avatarβ¦
<form method="post" class="avatarform" id="avatarform" action="{% url avatar_update_view' %}" enctype="multipart/form-data">
{% csrf_token %}
<input id="avatarUpload" class="d-none" type="file" name="avatar">
</form>
Then, setting the new image in the view is as easy as the following (where profile is the profile model for the self.request.user)
profile.avatar.image_file.save(self.request.FILES['avatar'].name, self.request.FILES['avatar'])
There is no need to save the profile.avatar, the image_field already saves, and into the correct location because of the βupload_toβ callback function.
- [Django]-How to resize an ImageField image before saving it in python Django model
- [Django]-Django template includes slow?
- [Django]-Django-Forms with json fields
0π
I save the image with uuid in django 2 python 3 because thats how django do it:
import uuid
from django.core.files import File
import urllib
httpUrl = "https://miimgeurl/image.jpg"
result = urllib.request.urlretrieve(httpUrl)
mymodel.imagefield.save(os.path.basename(str(uuid.uuid4())+".jpg"),File(open(result[0], 'rb')))
mymodel.save()
- [Django]-Serializer call is showing an TypeError: Object of type 'ListSerializer' is not JSON serializable?
- [Django]-What's the best way to extend the User model in Django?
- [Django]-Paginate relationship in Django REST Framework?
0π
if you use admin.py you can solve the problem override (doc on django):
def save_model(self, request, obj, form, change):
obj.image_data = bytes(obj.image_name.read())
super().save_model(request, obj, form, change)
with models.py:
image_name = models.ImageField()
image_data = models.BinaryField()
- [Django]-How to test Django's UpdateView?
- [Django]-Http POST drops port in URL
- [Django]-How to run own daemon processes with Django?
0π
Just for those who have struggled with this issue for some time. I spent a few hours to understand what is needed in order to store from code an image into an ImageField in Django. You have to pass a File object to the ImageField as described in the sample below, the file must be opened, and you have to save the model containing your ImageField before closing the file. This sample works fine:
from pathlib import Path
from django.core.files import File
path = Path(image_file_str_path)
with path.open(mode="rb") as f:
yourmodel.img_field = File(f, name=path.name)
yourmodel.save()
- [Django]-Cron and virtualenv
- [Django]-Unittest Django: Mock external API, what is proper way?
- [Django]-What is reverse()?
-1π
Your can use Django REST framework and python Requests library to Programmatically saving image to Django ImageField
Here is a Example:
import requests
def upload_image():
# PATH TO DJANGO REST API
url = "http://127.0.0.1:8080/api/gallery/"
# MODEL FIELDS DATA
data = {'first_name': "Rajiv", 'last_name': "Sharma"}
# UPLOAD FILES THROUGH REST API
photo = open('/path/to/photo', 'rb')
resume = open('/path/to/resume', 'rb')
files = {'photo': photo, 'resume': resume}
request = requests.post(url, data=data, files=files)
print(request.status_code, request.reason)
- [Django]-Running Django with FastCGI or with mod_python
- [Django]-Why is factory_boy superior to using the ORM directly in tests?
- [Django]-Default filter in Django model