How to access media files uploaded via a Django form? - python

I am accepting an image from the user in a form in Django. How do I access the uploaded image to show it in the web browser?
This is what I have in settings.py
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'
This is in my models.py
class Hotel(models.Model):
name = models.CharField(max_length=50)
image = models.ImageField(upload_to="images/")
Also, I have added the
if settings.DEBUG:
urlpatterns +=static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)
in urls.py
I tried to access the image as
def image_view(request):
if request.method=='POST':
farm = hotelForm();
form = hotelForm(request.POST,request.FILES)
if form.is_valid():
form.save()
modelff = Hotel(name=request.POST['name'],image = request.FILES['image'])
# print(modelff.image.url)
return render(request,'djangoform.html',{"form":farm,"uploaded_data_url":modelff.image.url})
else:
form = hotelForm()
return render(request,'djangoform.html',{"form":form})
And in my template, I accessed the image as <img src="{{uploaded_data_url}}">. But the image does not show up and the console shows image not found.
P.S. I have seen How to access media files in django How to access uploaded files in Django?
https://docs.djangoproject.com/en/dev/howto/static-files/#serving-files-uploaded-by-a-user-during-development
Django : accessing uploaded picture from ImageField
But none of them seem to help me. I can't find how do I include the 'images/' in my path. My uploaded_data_url shows /media/Screenshot%202020-04-18%20at%206.39.24%20PM.png while I expect it to show /media/images/Screenshot%202020-04-18%20at%206.39.24%20PM.png
Where is the problem?
Also, if there can be something similar to How can I get uploaded text file in view through Django? (f.read() in this question) It would be great.
Edit: Since from an answer, it seems the question was not clear, I would like to clarify that the above was just what I tried and I don't really know if it is correct or not. Secondly, the whole purpose of doing this was to get image from user, process it, and display the original and final image to the user. So if there is any other method that you have to do this, please share that.

If the uploaded_data_url shows this /media/Screenshot%202020-04-18%20at%206.39.24%20PM.png then this means that the images were saved under the media dir. This is expected since your conf is MEDIA_URL = '/media/'.
If you want it as /media/images/Screenshot%202020-04-18%20at%206.39.24%20PM.png then change to this MEDIA_URL = '/media/images/'.
The problem with the above is that it will interfere with all other media files, so a simpler solution would be to replace the /media/ with /media/images/.
Adapt this in your views.py
url = str(modelff.image.url)
modUrl = url.replace("/media/","/media/images/")
return render(request,'djangoform.html',{"form":farm,"uploaded_data_url":modUrl l})

Related

Trouble with media directory/files on pythonanywhere

I seem to be having an issue serving up media content on my website. Everything works fine when run on localhost. However, when deployed to python anywhere, I receive a FileNotFoundError when I attempt to upload an image via a form.
I've taken a look through overflow for some related topics however I've not found any threads which have allowed me to solve my problem.
Here is the exact error received when submitting the image upload form:
It seems to be an issue with the resize method in models.py (which works fine on localhost)
Here are the appropriate setup files:
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
...
MEDIA_DIR = os.path.join(BASE_DIR, 'media')
# Media
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
IMAGES_DIR = os.path.join(MEDIA_URL,"images")
I believe the error is due to the images_path method not retuning the correct location (but it works on localhost). Here is the model which stores the image and defines how images are saved:
models.py
class Image(models.Model):
# this might work?
def images_path():
return os.path.join(settings.IMAGES_DIR, 'usruploads')
def resize(self):
im = PIL.Image.open(self.image)
size=(200,200)
out = im.resize(size)
out.save(self.image.__str__())
def save(self, *args, **kwargs):
super(Image, self).save(*args, **kwargs)
self.resize()
image = models.ImageField(upload_to=images_path()[1:], max_length=255)
I will also throw in the media directory structure of the site in case this info is of use.
This is my first attempt at a deploying a Django web app via python anywhere so hopefully once this issue is fixed, it is a mistake I will never make again.
I have implemented the change you suggestd and the referenced url exists which is now a start however the server is claiming that it does not.
I have printed out the URL and path of the image as follows:
I can go to the index page and enter this url and it loads the image.
Ok, your suggestion was correct uring path instead of __str__() worked. The reason the issue second issue was occurring was then due to the fact that I was opening the image using url and trying to save it using path it did not like this. Thanks for your help!
Given
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
IMAGES_DIR = os.path.join(MEDIA_URL,"images")
and
class Image(models.Model):
# this might work?
def images_path():
return os.path.join(settings.IMAGES_DIR, 'usruploads')
def resize(self):
im = PIL.Image.open(self.image)
size=(200,200)
out = im.resize(size)
out.save(self.image.__str__())
def save(self, *args, **kwargs):
super(Image, self).save(*args, **kwargs)
self.resize()
image = models.ImageField(upload_to=images_path()[1:], max_length=255)
We can infer that
IMAGES_DIR = "/media/images"
and
image = models.ImageField(upload_to='media/images/usruploads', max_length=255)
That means files are uploaded to /<base_dir>/media/media/images/usruploads.
Issue
Looking at your logs, the error happens at the end of your logs.
...
out.save(self.image.__str__())
The issue is self.image.__str__() returns the relative path/filename of the file, and when you pass a relative path to out.save , it will try to save that file in the provided path RELATIVE TO THE CURRENT WORKING DIRECTORY.
Solution
What you have to do instead (assuming you want to replace the original image) is pass the absolute path of the original image:
...
out.save(self.image.path)

Django - How to save files to STATIC_ROOT from views?

I have made a Django app that takes arguments from the form and makes an image using Pillow.
views.py:
file_name = "{}.png".format(random.randint(1, 255))
image1.save(file_name)
pretty simple stuff, right? Now when I try to render that image with HttpResponse as:
return HttpResponse("<img src='" +file_name + "' alt='image here'>")
apparently, it will throw an error. Can you please tell me what to do in order to save it properly and show in HttpResponse?
Django==1.11.8
Pillow==5.0.0
Python 3.6.2
Thank you!
Firstly, you should be saving to MEDIA_ROOT. Secondly, you need to put an actual URL - ie relative to MEDIA_URL - in your img src, not just a filename. Third, you need to have something serving files at that URL.

Best way to retrieve the url of a imageField in django

I'm using the following models:
class Product(models.Model):
# some other stuff
pictures = models.ManyToManyField(Image)
class Image(models.Model):
# MEDIA_ROOT = /full/path/to/my/media/folder/
image = models.ImageField(upload_to=settings.MEDIA_ROOT, default=DEFAULT_PROFILE_PICTURE)
Then in a view I wan to retrieve the images so i run the following code:
for pic in product.pictures.all():
pictures += [pic.image.url.replace(settings.PROJECT_ROOT, url)]
The problem here is that pic.image.url is giving me the system path, and I was expecting the relative path (something like /media/mypicture.jpg) so to fix this I used the replace function, but it looks to me that it should be a better way.
How can I build the model or access the image to avoid using the replace method?
Thanks in advance
You shouldn't use MEDIA_ROOT as a upload_to value. If you want to upload to MEDIA_ROOT without any subdirctories then just use an empty string '':
image = models.ImageField(upload_to='')

ImageField Upload with Django

I am trying to upload an image with django and so far i can't see the upload_to directory get created or any file source in the database field.
My Model.
class Person(models.Model):
photo = models.ImageField(upload_to='profiles/', null=True, blank=True)
My View
def create_profile(request):
if request.method == "POST":
form = PartialPersonForm(request.POST, request.FILES,)
addressForm = PartialAddressForm(request.POST)
When i upload and save, i dont get any sort of errors. Anyway i can debug this and find out if the photo field is set.
<div class="photo-upload">{{ form.photo|attr:"onchange:readURL(this);" }}
Unless you're doing something special with regard to media storage, you should set up MEDIA_ROOT to the directory where you want the uploaded files to be saved.
When dealing with file-type fields, you will need to following instructions in the Django documentation for FileField.storage.
In your view, you will need to save() the uploaded form data.
def create_profile(request):
if request.method == "POST":
form = PartialPersonForm(request.POST, request.FILES,)
addressForm = PartialAddressForm(request.POST)
form.save()
addressForm.save()
i believe you should create the upload_to directory yourself. Also make sure to set the appropriate permissions for the directory, otherwise it won't be able to write in it.

How do I properly display user-generated images using django?

I am trying to upload a user-generated image and then display in on my django web app. The image is getting uploaded to the server but I am having trouble displaying it.
models.py
image = models.ImageField(blank=True, null=True, max_length=255, upload_to="images/")
settings.py
MEDIA_ROOT = '/home/user/webapps/static/'
MEDIA_URL = 'http://user.webfactional.com/static/'
As an example, say I upload I file named Finland.gif. I can see the file uploaded. However when I look at the source, I see the source of the image as "www.foo.com/accounts/profile/images/Finland.gif" and not the static image url which should be "http://user.webfactional.com/static/images/Finland.gif". Any advice on how I should fix this?
userprofile.image.url gives you the full url to the image
Just solved it... I need to include:
http://user.webfactional.com/static/{{userprofile.image}}

Categories

Resources